diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 34070f3b2b..07dc4dad77 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -22,6 +22,7 @@ /avm/ptn/azd/ml-hub-dependencies/ @Azure/avm-ptn-azd-mlhubdependencies-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/ptn/azd/ml-project/ @Azure/avm-ptn-azd-mlproject-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/ptn/azd/monitoring/ @Azure/avm-ptn-azd-monitoring-module-owners-bicep @Azure/avm-module-reviewers-bicep +/avm/ptn/data/private-analytical-workspace/ @Azure/avm-ptn-data-privateanalyticalworkspace-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/ptn/deployment-script/import-image-to-acr/ @Azure/avm-ptn-deploymentscript-importimagetoacr-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/ptn/dev-ops/cicd-agents-and-runners/ @Azure/avm-ptn-devops-cicdagentsandrunners-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/ptn/finops-toolkit/finops-hub/ @Azure/avm-ptn-finopstoolkit-finopshub-module-owners-bicep @Azure/avm-module-reviewers-bicep @@ -171,4 +172,5 @@ /avm/res/web/serverfarm/ @Azure/avm-res-web-serverfarm-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/web/site/ @Azure/avm-res-web-site-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/web/static-site/ @Azure/avm-res-web-staticsite-module-owners-bicep @Azure/avm-module-reviewers-bicep +/avm/utl/types/avm-common-types/ @Azure/avm-utl-types-avmcommontypes-module-owners-bicep @Azure/avm-module-reviewers-bicep *avm.core.team.tests.ps1 @Azure/avm-core-team-technical-bicep diff --git a/.github/ISSUE_TEMPLATE/avm_module_issue.yml b/.github/ISSUE_TEMPLATE/avm_module_issue.yml index 56d3fb70d3..7ff72be0e8 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -57,6 +57,7 @@ body: - "avm/ptn/azd/ml-hub-dependencies" - "avm/ptn/azd/ml-project" - "avm/ptn/azd/monitoring" + - "avm/ptn/data/private-analytical-workspace" - "avm/ptn/deployment-script/import-image-to-acr" - "avm/ptn/dev-ops/cicd-agents-and-runners" - "avm/ptn/finops-toolkit/finops-hub" @@ -206,6 +207,7 @@ body: - "avm/res/web/serverfarm" - "avm/res/web/site" - "avm/res/web/static-site" + - "avm/utl/types/avm-common-types" validations: required: true - type: input diff --git a/.github/actions/templates/avm-validateModuleDeployment/action.yml b/.github/actions/templates/avm-validateModuleDeployment/action.yml index 715a2f642b..b272554729 100644 --- a/.github/actions/templates/avm-validateModuleDeployment/action.yml +++ b/.github/actions/templates/avm-validateModuleDeployment/action.yml @@ -327,7 +327,7 @@ runs: Write-Output ('{0}={1}' -f 'deploymentNames', ($res.deploymentNames | ConvertTo-Json -Compress)) >> $env:GITHUB_OUTPUT # Populate further outputs - $deploymentOutput = $res.deploymentOutput | ConvertTo-Json -Depth 99 -Compress + $deploymentOutput = ($res.deploymentOutput | ConvertTo-Json -Depth 99 -Compress) -replace "'", "''" # Escaping single quotes for resilient access in subsequent steps Write-Output ('{0}={1}' -f 'deploymentOutput', $deploymentOutput) >> $env:GITHUB_OUTPUT Write-Verbose "Deployment output: $deploymentOutput" -Verbose diff --git a/.github/actions/templates/avm-validateModulePSRule/action.yml b/.github/actions/templates/avm-validateModulePSRule/action.yml index 88c123fca6..ab29a6d245 100644 --- a/.github/actions/templates/avm-validateModulePSRule/action.yml +++ b/.github/actions/templates/avm-validateModulePSRule/action.yml @@ -131,6 +131,35 @@ runs: source: "${{ inputs.psrulePath}}/.ps-rule/" # Path to folder containing suppression rules to use for analysis. summary: false # Disabling as taken care in customized task + - name: Run PSRule analysis - Security Pillar Only (Custom Security Pillar) + uses: microsoft/ps-rule@v2.9.0 + if: ${{ inputs.psruleBaseline == 'CB.AVM.WAF.Security' }} + with: + modules: "PSRule.Rules.Azure" + prerelease: true + baseline: "${{ inputs.psruleBaseline }}" + inputPath: "${{ inputs.templateFilePath}}" + outputFormat: Csv + outputPath: "${{ inputs.templateFilePath}}-PSRule-output.csv" + option: "${{ github.workspace }}/${{ inputs.psrulePath}}/ps-rule.yaml" # Path to PSRule configuration options file + source: "${{ inputs.psrulePath}}/.ps-rule/" # Path to folder containing suppression rules to use for analysis. + summary: false # Disabling as taken care in customized task + + - name: Run PSRule analysis - Security Pillar Only (Azure.Pillar.Security) + uses: microsoft/ps-rule@v2.9.0 + if: ${{ inputs.psruleBaseline == 'Azure.Pillar.Security' }} + continue-on-error: true + with: + modules: "PSRule.Rules.Azure" + prerelease: true + baseline: "${{ inputs.psruleBaseline }}" + inputPath: "${{ inputs.templateFilePath}}" + outputFormat: Csv + outputPath: "${{ inputs.templateFilePath}}-PSRule-output.csv" + option: "${{ github.workspace }}/${{ inputs.psrulePath}}/ps-rule.yaml" # Path to PSRule configuration options file + source: "${{ inputs.psrulePath}}/.ps-rule/" # Path to folder containing suppression rules to use for analysis. + summary: false # Disabling as taken care in customized task + - name: "Parse CSV content" if: always() uses: azure/powershell@v2 diff --git a/.github/workflows/avm.ptn.data.private-analytical-workspace.yml b/.github/workflows/avm.ptn.data.private-analytical-workspace.yml new file mode 100644 index 0000000000..c0521d0504 --- /dev/null +++ b/.github/workflows/avm.ptn.data.private-analytical-workspace.yml @@ -0,0 +1,88 @@ +name: "avm.ptn.data.private-analytical-workspace" + +on: + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + customLocation: + type: string + description: "Default location overwrite (e.g., eastus)" + required: false + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.ptn.data.private-analytical-workspace.yml" + - "avm/ptn/data/private-analytical-workspace/**" + - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" + - "!*/**/README.md" + +env: + modulePath: "avm/ptn/data/private-analytical-workspace" + workflowPath: ".github/workflows/avm.ptn.data.private-analytical-workspace.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/.github/workflows/avm.ptn.deployment-script.import-image-to-acr.yml b/.github/workflows/avm.ptn.deployment-script.import-image-to-acr.yml index 1dc2c635a1..6f0179678d 100644 --- a/.github/workflows/avm.ptn.deployment-script.import-image-to-acr.yml +++ b/.github/workflows/avm.ptn.deployment-script.import-image-to-acr.yml @@ -1,8 +1,6 @@ name: "avm.ptn.deployment-script.import-image-to-acr" on: - schedule: - - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) workflow_dispatch: inputs: staticValidation: diff --git a/.github/workflows/avm.res.hybrid-compute.machine.yml b/.github/workflows/avm.res.hybrid-compute.machine.yml index 1b37947d8e..6e6103ad2d 100644 --- a/.github/workflows/avm.res.hybrid-compute.machine.yml +++ b/.github/workflows/avm.res.hybrid-compute.machine.yml @@ -1,8 +1,6 @@ name: "avm.res.hybrid-compute.machine" on: - schedule: - - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) workflow_dispatch: inputs: staticValidation: diff --git a/.github/workflows/avm.template.module.yml b/.github/workflows/avm.template.module.yml index 4df961c68e..f7b409ce9a 100644 --- a/.github/workflows/avm.template.module.yml +++ b/.github/workflows/avm.template.module.yml @@ -94,6 +94,50 @@ jobs: psrulePath: "avm/utilities/pipelines/staticValidation/psrule" #'${{ github.workspace }}/avm' psruleBaseline: "Azure.Pillar.Reliability" + job_psrule_test_waf_security_cb: # Note: Please don't change this job name. It is used by the setEnvironment action to define which PS modules to install on runners. + name: "PSRule - WAF Security - AVM Custom Baseline [${{ matrix.testCases.name }}]" + runs-on: ubuntu-latest + if: ${{ inputs.psRuleModuleTestFilePaths != '' && (fromJson(inputs.workflowInput)).staticValidation == 'true' }} + strategy: + fail-fast: false + matrix: + testCases: ${{ fromJson(inputs.psRuleModuleTestFilePaths) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set environment + uses: ./.github/actions/templates/avm-setEnvironment + - name: "Run PSRule validation with [${{ matrix.testCases.path }}]" + uses: ./.github/actions/templates/avm-validateModulePSRule + with: + templateFilePath: "${{ inputs.modulePath }}/${{ matrix.testCases.path }}" + subscriptionId: "${{ secrets.ARM_SUBSCRIPTION_ID }}" + managementGroupId: "${{ secrets.ARM_MGMTGROUP_ID }}" + psrulePath: "avm/utilities/pipelines/staticValidation/psrule" #'${{ github.workspace }}/avm' + psruleBaseline: "CB.AVM.WAF.Security" + + job_psrule_test_waf_security: # Note: Please don't change this job name. It is used by the setEnvironment action to define which PS modules to install on runners. + name: "PSRule - WAF Security [${{ matrix.testCases.name }}]" + runs-on: ubuntu-latest + if: ${{ inputs.psRuleModuleTestFilePaths != '' && (fromJson(inputs.workflowInput)).staticValidation == 'true' }} + strategy: + fail-fast: false + matrix: + testCases: ${{ fromJson(inputs.psRuleModuleTestFilePaths) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set environment + uses: ./.github/actions/templates/avm-setEnvironment + - name: "Run PSRule validation with [${{ matrix.testCases.path }}]" + uses: ./.github/actions/templates/avm-validateModulePSRule + with: + templateFilePath: "${{ inputs.modulePath }}/${{ matrix.testCases.path }}" + subscriptionId: "${{ secrets.ARM_SUBSCRIPTION_ID }}" + managementGroupId: "${{ secrets.ARM_MGMTGROUP_ID }}" + psrulePath: "avm/utilities/pipelines/staticValidation/psrule" #'${{ github.workspace }}/avm' + psruleBaseline: "Azure.Pillar.Security" + ############################# # Deployment validation # ############################# @@ -104,10 +148,12 @@ jobs: !cancelled() && (fromJson(inputs.workflowInput)).deploymentValidation == 'true' && needs.job_module_static_validation.result != 'failure' && - needs.job_psrule_test_waf_reliability.result != 'failure' + needs.job_psrule_test_waf_reliability.result != 'failure' && + needs.job_psrule_test_waf_security_cb.result != 'failure' needs: - job_module_static_validation - job_psrule_test_waf_reliability + - job_psrule_test_waf_security_cb strategy: fail-fast: false matrix: diff --git a/.github/workflows/avm.utl.types.avm-common-types.yml b/.github/workflows/avm.utl.types.avm-common-types.yml new file mode 100644 index 0000000000..f2eac7c8c0 --- /dev/null +++ b/.github/workflows/avm.utl.types.avm-common-types.yml @@ -0,0 +1,88 @@ +name: "avm.utl.types.avm-common-types" + +on: + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + customLocation: + type: string + description: "Default location overwrite (e.g., eastus)" + required: false + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.utl.types.avm-common-types.yml" + - "avm/utl/types/avm-common-types/**" + - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" + - "!*/**/README.md" + +env: + modulePath: "avm/utl/types/avm-common-types" + workflowPath: ".github/workflows/avm.utl.types.avm-common-types.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/.github/workflows/platform.ossf-scorecard.yml b/.github/workflows/platform.ossf-scorecard.yml index b6f8d9fa50..e387559274 100644 --- a/.github/workflows/platform.ossf-scorecard.yml +++ b/.github/workflows/platform.ossf-scorecard.yml @@ -59,7 +59,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@84480863f228bb9747b473957fcc9e309aa96097 # v4.4.2 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: SARIF file path: results.sarif @@ -68,6 +68,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + uses: github/codeql-action/upload-sarif@396bb3e45325a47dd9ef434068033c6d5bb0d11a # v3.27.3 with: sarif_file: results.sarif diff --git a/.github/workflows/platform.publish-module-index-json.yml b/.github/workflows/platform.publish-module-index-json.yml index 2d2d3eac69..cc3fc468b6 100644 --- a/.github/workflows/platform.publish-module-index-json.yml +++ b/.github/workflows/platform.publish-module-index-json.yml @@ -74,7 +74,7 @@ jobs: } - name: Upload artifacts - uses: actions/upload-artifact@v4.4.2 + uses: actions/upload-artifact@v4.4.3 with: name: publish-module-index-json-artifacts path: | diff --git a/avm/ptn/ai-platform/baseline/README.md b/avm/ptn/ai-platform/baseline/README.md index 7676df01c3..7456f6c787 100644 --- a/avm/ptn/ai-platform/baseline/README.md +++ b/avm/ptn/ai-platform/baseline/README.md @@ -56,9 +56,9 @@ By integrating with Microsoft Entra ID for secure identity management and utiliz | `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints/privateDnsZoneGroups) | | `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints/privateDnsZoneGroups) | | `Microsoft.Network/publicIPAddresses` | [2023-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-09-01/publicIPAddresses) | -| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks) | -| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/subnets) | -| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/virtualNetworkPeerings) | +| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks) | +| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/subnets) | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/virtualNetworkPeerings) | | `Microsoft.OperationalInsights/workspaces` | [2023-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2023-09-01/workspaces) | | `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupFabrics/protectionContainers/protectedItems) | | `Microsoft.Storage/storageAccounts` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Storage/2022-09-01/storageAccounts) | @@ -864,10 +864,10 @@ param workspaceConfiguration = { | [`keyVaultConfiguration`](#parameter-keyvaultconfiguration) | object | Configuration for the key vault. | | [`location`](#parameter-location) | string | Location for all Resources. | | [`logAnalyticsConfiguration`](#parameter-loganalyticsconfiguration) | object | Configuration for the Log Analytics workspace. | -| [`managedIdentityName`](#parameter-managedidentityname) | string | The name of the user assigned identity for the AI Studio hub. If not provided, the hub will use a system assigned identity. | +| [`managedIdentityName`](#parameter-managedidentityname) | string | The name of the user-assigned identity for the AI Studio hub. If not provided, the hub will use a system-assigned identity. | | [`storageAccountConfiguration`](#parameter-storageaccountconfiguration) | object | Configuration for the storage account. | | [`tags`](#parameter-tags) | object | Resource tags. | -| [`virtualMachineConfiguration`](#parameter-virtualmachineconfiguration) | secureObject | Configuration for the virtual machine. | +| [`virtualMachineConfiguration`](#parameter-virtualmachineconfiguration) | object | Configuration for the virtual machine. | | [`virtualNetworkConfiguration`](#parameter-virtualnetworkconfiguration) | object | Configuration for the virtual network. | | [`workspaceConfiguration`](#parameter-workspaceconfiguration) | object | Configuration for the AI Studio workspace. | @@ -1106,7 +1106,7 @@ The name of the Log Analytics workspace. ### Parameter: `managedIdentityName` -The name of the user assigned identity for the AI Studio hub. If not provided, the hub will use a system assigned identity. +The name of the user-assigned identity for the AI Studio hub. If not provided, the hub will use a system-assigned identity. - Required: No - Type: string @@ -1172,7 +1172,304 @@ Resource tags. Configuration for the virtual machine. - Required: No -- Type: secureObject +- Type: object + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`adminPassword`](#parameter-virtualmachineconfigurationadminpassword) | securestring | The password for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module. | +| [`adminUsername`](#parameter-virtualmachineconfigurationadminusername) | string | The username for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enableAadLoginExtension`](#parameter-virtualmachineconfigurationenableaadloginextension) | bool | Whether to enable the Microsoft.Azure.ActiveDirectory AADLoginForWindows extension, allowing users to log in to the virtual machine using Microsoft Entra. Defaults to 'false'. | +| [`enableAzureMonitorAgent`](#parameter-virtualmachineconfigurationenableazuremonitoragent) | bool | Whether to enable the Microsoft.Azure.Monitor AzureMonitorWindowsAgent extension. Defaults to 'false'. | +| [`enabled`](#parameter-virtualmachineconfigurationenabled) | bool | Whether to create a virtual machine in the associated virtual network. Defaults to 'true'. | +| [`encryptionAtHost`](#parameter-virtualmachineconfigurationencryptionathost) | bool | 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'. | +| [`imageReference`](#parameter-virtualmachineconfigurationimagereference) | 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. | +| [`maintenanceConfigurationResourceId`](#parameter-virtualmachineconfigurationmaintenanceconfigurationresourceid) | string | The resource Id of a maintenance configuration for the virtual machine. | +| [`name`](#parameter-virtualmachineconfigurationname) | string | The name of the virtual machine. | +| [`nicConfigurationConfiguration`](#parameter-virtualmachineconfigurationnicconfigurationconfiguration) | object | Configuration for the virtual machine network interface. | +| [`osDisk`](#parameter-virtualmachineconfigurationosdisk) | object | Specifies the OS disk. | +| [`patchMode`](#parameter-virtualmachineconfigurationpatchmode) | string | VM guest patching orchestration mode. Refer to 'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching'. | +| [`size`](#parameter-virtualmachineconfigurationsize) | string | The virtual machine size. Defaults to 'Standard_D2s_v3'. | +| [`zone`](#parameter-virtualmachineconfigurationzone) | int | The availability zone of the virtual machine. If set to 0, no availability zone is used (default). | + +### Parameter: `virtualMachineConfiguration.adminPassword` + +The password for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module. + +- Required: No +- Type: securestring + +### Parameter: `virtualMachineConfiguration.adminUsername` + +The username for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module. + +- Required: No +- Type: string + +### Parameter: `virtualMachineConfiguration.enableAadLoginExtension` + +Whether to enable the Microsoft.Azure.ActiveDirectory AADLoginForWindows extension, allowing users to log in to the virtual machine using Microsoft Entra. Defaults to 'false'. + +- Required: No +- Type: bool + +### Parameter: `virtualMachineConfiguration.enableAzureMonitorAgent` + +Whether to enable the Microsoft.Azure.Monitor AzureMonitorWindowsAgent extension. Defaults to 'false'. + +- Required: No +- Type: bool + +### Parameter: `virtualMachineConfiguration.enabled` + +Whether to create a virtual machine in the associated virtual network. Defaults to 'true'. + +- Required: No +- Type: bool + +### Parameter: `virtualMachineConfiguration.encryptionAtHost` + +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'. + +- Required: No +- Type: bool + +### Parameter: `virtualMachineConfiguration.imageReference` + +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. + +- Required: No +- Type: object + +### Parameter: `virtualMachineConfiguration.maintenanceConfigurationResourceId` + +The resource Id of a maintenance configuration for the virtual machine. + +- Required: No +- Type: string + +### Parameter: `virtualMachineConfiguration.name` + +The name of the virtual machine. + +- Required: No +- Type: string + +### Parameter: `virtualMachineConfiguration.nicConfigurationConfiguration` + +Configuration for the virtual machine network interface. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`ipConfigName`](#parameter-virtualmachineconfigurationnicconfigurationconfigurationipconfigname) | string | The name of the IP configuration. | +| [`name`](#parameter-virtualmachineconfigurationnicconfigurationconfigurationname) | string | The name of the network interface. | +| [`networkSecurityGroupResourceId`](#parameter-virtualmachineconfigurationnicconfigurationconfigurationnetworksecuritygroupresourceid) | string | The resource ID of an existing network security group to associate with the network interface. | +| [`privateIPAllocationMethod`](#parameter-virtualmachineconfigurationnicconfigurationconfigurationprivateipallocationmethod) | string | The private IP address allocation method. | + +### Parameter: `virtualMachineConfiguration.nicConfigurationConfiguration.ipConfigName` + +The name of the IP configuration. + +- Required: No +- Type: string + +### Parameter: `virtualMachineConfiguration.nicConfigurationConfiguration.name` + +The name of the network interface. + +- Required: No +- Type: string + +### Parameter: `virtualMachineConfiguration.nicConfigurationConfiguration.networkSecurityGroupResourceId` + +The resource ID of an existing network security group to associate with the network interface. + +- Required: No +- Type: string + +### Parameter: `virtualMachineConfiguration.nicConfigurationConfiguration.privateIPAllocationMethod` + +The private IP address allocation method. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Dynamic' + 'Static' + ] + ``` + +### Parameter: `virtualMachineConfiguration.osDisk` + +Specifies the OS disk. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`managedDisk`](#parameter-virtualmachineconfigurationosdiskmanageddisk) | object | The managed disk parameters. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`caching`](#parameter-virtualmachineconfigurationosdiskcaching) | string | Specifies the caching requirements. | +| [`createOption`](#parameter-virtualmachineconfigurationosdiskcreateoption) | string | Specifies how the virtual machine should be created. | +| [`deleteOption`](#parameter-virtualmachineconfigurationosdiskdeleteoption) | string | Specifies whether data disk should be deleted or detached upon VM deletion. | +| [`diskSizeGB`](#parameter-virtualmachineconfigurationosdiskdisksizegb) | int | Specifies the size of an empty data disk in gigabytes. | +| [`name`](#parameter-virtualmachineconfigurationosdiskname) | string | The disk name. | + +### Parameter: `virtualMachineConfiguration.osDisk.managedDisk` + +The managed disk parameters. + +- Required: Yes +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`diskEncryptionSetResourceId`](#parameter-virtualmachineconfigurationosdiskmanageddiskdiskencryptionsetresourceid) | string | Specifies the customer managed disk encryption set resource id for the managed disk. | +| [`storageAccountType`](#parameter-virtualmachineconfigurationosdiskmanageddiskstorageaccounttype) | string | Specifies the storage account type for the managed disk. | + +### Parameter: `virtualMachineConfiguration.osDisk.managedDisk.diskEncryptionSetResourceId` + +Specifies the customer managed disk encryption set resource id for the managed disk. + +- Required: No +- Type: string + +### Parameter: `virtualMachineConfiguration.osDisk.managedDisk.storageAccountType` + +Specifies the storage account type for the managed disk. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Premium_LRS' + 'Premium_ZRS' + 'PremiumV2_LRS' + 'Standard_LRS' + 'StandardSSD_LRS' + 'StandardSSD_ZRS' + 'UltraSSD_LRS' + ] + ``` + +### Parameter: `virtualMachineConfiguration.osDisk.caching` + +Specifies the caching requirements. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'None' + 'ReadOnly' + 'ReadWrite' + ] + ``` + +### Parameter: `virtualMachineConfiguration.osDisk.createOption` + +Specifies how the virtual machine should be created. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Attach' + 'Empty' + 'FromImage' + ] + ``` + +### Parameter: `virtualMachineConfiguration.osDisk.deleteOption` + +Specifies whether data disk should be deleted or detached upon VM deletion. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Delete' + 'Detach' + ] + ``` + +### Parameter: `virtualMachineConfiguration.osDisk.diskSizeGB` + +Specifies the size of an empty data disk in gigabytes. + +- Required: No +- Type: int + +### Parameter: `virtualMachineConfiguration.osDisk.name` + +The disk name. + +- Required: No +- Type: string + +### Parameter: `virtualMachineConfiguration.patchMode` + +VM guest patching orchestration mode. Refer to 'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching'. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AutomaticByOS' + 'AutomaticByPlatform' + 'Manual' + ] + ``` + +### Parameter: `virtualMachineConfiguration.size` + +The virtual machine size. Defaults to 'Standard_D2s_v3'. + +- Required: No +- Type: string + +### Parameter: `virtualMachineConfiguration.zone` + +The availability zone of the virtual machine. If set to 0, no availability zone is used (default). + +- Required: No +- Type: int +- Allowed: + ```Bicep + [ + 0 + 1 + 2 + 3 + ] + ``` ### Parameter: `virtualNetworkConfiguration` diff --git a/avm/ptn/ai-platform/baseline/main.bicep b/avm/ptn/ai-platform/baseline/main.bicep index cfa8b0f7d7..5a111268da 100644 --- a/avm/ptn/ai-platform/baseline/main.bicep +++ b/avm/ptn/ai-platform/baseline/main.bicep @@ -17,35 +17,35 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -@description('Optional. The name of the user assigned identity for the AI Studio hub. If not provided, the hub will use a system assigned identity.') +@description('Optional. The name of the user-assigned identity for the AI Studio hub. If not provided, the hub will use a system-assigned identity.') param managedIdentityName string? @description('Optional. Configuration for the Log Analytics workspace.') -param logAnalyticsConfiguration logAnalyticsConfigurationType +param logAnalyticsConfiguration logAnalyticsConfigurationType? @description('Optional. Configuration for the key vault.') -param keyVaultConfiguration keyVaultConfigurationType +param keyVaultConfiguration keyVaultConfigurationType? @description('Optional. Configuration for the storage account.') -param storageAccountConfiguration storageAccountConfigurationType +param storageAccountConfiguration storageAccountConfigurationType? @description('Optional. Configuration for the container registry.') -param containerRegistryConfiguration containerRegistryConfigurationType +param containerRegistryConfiguration containerRegistryConfigurationType? @description('Optional. Configuration for Application Insights.') -param applicationInsightsConfiguration applicationInsightsConfigurationType +param applicationInsightsConfiguration applicationInsightsConfigurationType? @description('Optional. Configuration for the AI Studio workspace.') -param workspaceConfiguration workspaceConfigurationType +param workspaceConfiguration workspaceConfigurationType? @description('Optional. Configuration for the virtual network.') -param virtualNetworkConfiguration virtualNetworkConfigurationType +param virtualNetworkConfiguration virtualNetworkConfigurationType? @description('Optional. Configuration for the Azure Bastion host.') -param bastionConfiguration bastionConfigurationType +param bastionConfiguration bastionConfigurationType? @description('Optional. Configuration for the virtual machine.') -param virtualMachineConfiguration virtualMachineConfigurationType +param virtualMachineConfiguration virtualMachineConfigurationType? // ============== // // Variables // @@ -617,19 +617,22 @@ output virtualMachineName string = createVirtualMachine ? virtualMachine.outputs // Definitions // // ================ // +@export() type logAnalyticsConfigurationType = { @description('Optional. The name of the Log Analytics workspace.') name: string? -}? +} +@export() type keyVaultConfigurationType = { @description('Optional. The name of the key vault.') name: string? @description('Optional. Provide \'true\' to enable Key Vault\'s purge protection feature. Defaults to \'true\'.') enablePurgeProtection: bool? -}? +} +@export() type storageAccountConfigurationType = { @description('Optional. The name of the storage account.') name: string? @@ -647,21 +650,24 @@ type storageAccountConfigurationType = { @description('Optional. Indicates whether the storage account permits requests to be authorized with the account access key via Shared Key. If false, then all requests, including shared access signatures, must be authorized with Microsoft Entra ID. Defaults to \'false\'.') allowSharedKeyAccess: bool? -}? +} +@export() type containerRegistryConfigurationType = { @description('Optional. The name of the container registry.') name: string? @description('Optional. Whether the trust policy is enabled for the container registry. Defaults to \'enabled\'.') trustPolicyStatus: 'enabled' | 'disabled'? -}? +} +@export() type applicationInsightsConfigurationType = { @description('Optional. The name of the Application Insights resource.') name: string? -}? +} +@export() type workspaceConfigurationType = { @description('Optional. The name of the AI Studio workspace hub.') name: string? @@ -676,8 +682,8 @@ type workspaceConfigurationType = { networkIsolationMode: 'AllowInternetOutbound' | 'AllowOnlyApprovedOutbound'? @description('Optional. The outbound rules for the managed network of the workspace hub.') - networkOutboundRules: networkOutboundRuleType -}? + networkOutboundRules: networkOutboundRuleType? +} type virtualNetworkSubnetConfigurationType = { @description('Optional. The name of the subnet to create.') @@ -688,8 +694,9 @@ type virtualNetworkSubnetConfigurationType = { @description('Optional. The resource ID of an existing network security group to associate with the subnet.') networkSecurityGroupResourceId: string? -}? +} +@export() type virtualNetworkConfigurationType = { @description('Optional. Whether to create an associated virtual network. Defaults to \'true\'.') enabled: bool? @@ -701,9 +708,10 @@ type virtualNetworkConfigurationType = { addressPrefix: string? @description('Optional. Configuration for the virual network subnet.') - subnet: virtualNetworkSubnetConfigurationType -}? + subnet: virtualNetworkSubnetConfigurationType? +} +@export() type bastionConfigurationType = { @description('Optional. Whether to create a Bastion host in the virtual network. Defaults to \'true\'.') enabled: bool? @@ -737,7 +745,7 @@ type bastionConfigurationType = { @description('Optional. The scale units for the Bastion Host resource.') scaleUnits: int? -}? +} type nicConfigurationConfigurationType = { @description('Optional. The name of the network interface.') @@ -751,7 +759,7 @@ type nicConfigurationConfigurationType = { @description('Optional. The resource ID of an existing network security group to associate with the network interface.') networkSecurityGroupResourceId: string? -}? +} type osDiskType = { @description('Optional. The disk name.') @@ -784,9 +792,9 @@ type osDiskType = { @description('Optional. Specifies the customer managed disk encryption set resource id for the managed disk.') diskEncryptionSetResourceId: string? } -}? +} -@secure() +@export() type virtualMachineConfigurationType = { @description('Optional. Whether to create a virtual machine in the associated virtual network. Defaults to \'true\'.') enabled: bool? @@ -798,23 +806,24 @@ type virtualMachineConfigurationType = { @description('Optional. The availability zone of the virtual machine. If set to 0, no availability zone is used (default).') zone: 0 | 1 | 2 | 3? - @description('Required. The virtual machine size. Defaults to \'Standard_D2s_v3\'.') + @description('Optional. The virtual machine size. Defaults to \'Standard_D2s_v3\'.') size: string? @description('Conditional. The username for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') adminUsername: string? @description('Conditional. The password for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') + @secure() adminPassword: string? @description('Optional. Configuration for the virtual machine network interface.') - nicConfigurationConfiguration: nicConfigurationConfigurationType + nicConfigurationConfiguration: nicConfigurationConfigurationType? @description('Optional. 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.') imageReference: object? @description('Optional. Specifies the OS disk.') - osDisk: osDiskType + osDisk: osDiskType? @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\'.') encryptionAtHost: bool? @@ -830,7 +839,7 @@ type virtualMachineConfigurationType = { @description('Optional. The resource Id of a maintenance configuration for the virtual machine.') maintenanceConfigurationResourceId: string? -}? +} @discriminator('type') type OutboundRuleType = FqdnOutboundRuleType | PrivateEndpointOutboundRule | ServiceTagOutboundRule @@ -890,4 +899,4 @@ type ServiceTagOutboundRule = { type networkOutboundRuleType = { @sys.description('Required. The outbound rule. The name of the rule is the object key.') *: OutboundRuleType -}? +} diff --git a/avm/ptn/ai-platform/baseline/main.json b/avm/ptn/ai-platform/baseline/main.json index cbb20a89d4..c12d3ffe40 100644 --- a/avm/ptn/ai-platform/baseline/main.json +++ b/avm/ptn/ai-platform/baseline/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "14190804454906731332" + "templateHash": "2870627868590310174" }, "name": "AI Platform Baseline", "description": "This module provides a secure and scalable environment for deploying AI applications on Azure.\nThe module encompasses all essential components required for building, managing, and observing AI solutions, including a machine learning workspace, observability tools, and necessary data management services.\nBy integrating with Microsoft Entra ID for secure identity management and utilizing private endpoints for services like Key Vault and Blob Storage, the module ensures secure communication and data access.", @@ -24,7 +24,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "keyVaultConfigurationType": { "type": "object", @@ -44,7 +46,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "storageAccountConfigurationType": { "type": "object", @@ -81,7 +85,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "containerRegistryConfigurationType": { "type": "object", @@ -105,7 +111,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "applicationInsightsConfigurationType": { "type": "object", @@ -118,7 +126,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "workspaceConfigurationType": { "type": "object", @@ -157,12 +167,15 @@ }, "networkOutboundRules": { "$ref": "#/definitions/networkOutboundRuleType", + "nullable": true, "metadata": { "description": "Optional. The outbound rules for the managed network of the workspace hub." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "virtualNetworkSubnetConfigurationType": { "type": "object", @@ -188,8 +201,7 @@ "description": "Optional. The resource ID of an existing network security group to associate with the subnet." } } - }, - "nullable": true + } }, "virtualNetworkConfigurationType": { "type": "object", @@ -217,12 +229,15 @@ }, "subnet": { "$ref": "#/definitions/virtualNetworkSubnetConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the virual network subnet." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "bastionConfigurationType": { "type": "object", @@ -309,7 +324,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "nicConfigurationConfigurationType": { "type": "object", @@ -346,8 +363,7 @@ "description": "Optional. The resource ID of an existing network security group to associate with the network interface." } } - }, - "nullable": true + } }, "osDiskType": { "type": "object", @@ -432,11 +448,10 @@ "description": "Required. The managed disk parameters." } } - }, - "nullable": true + } }, "virtualMachineConfigurationType": { - "type": "secureObject", + "type": "object", "properties": { "enabled": { "type": "bool", @@ -470,7 +485,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. The virtual machine size. Defaults to 'Standard_D2s_v3'." + "description": "Optional. The virtual machine size. Defaults to 'Standard_D2s_v3'." } }, "adminUsername": { @@ -481,7 +496,7 @@ } }, "adminPassword": { - "type": "string", + "type": "securestring", "nullable": true, "metadata": { "description": "Conditional. The password for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module." @@ -489,6 +504,7 @@ }, "nicConfigurationConfiguration": { "$ref": "#/definitions/nicConfigurationConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the virtual machine network interface." } @@ -502,6 +518,7 @@ }, "osDisk": { "$ref": "#/definitions/osDiskType", + "nullable": true, "metadata": { "description": "Optional. Specifies the OS disk." } @@ -547,7 +564,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "OutboundRuleType": { "type": "object", @@ -721,7 +740,6 @@ "description": "Required. The outbound rule. The name of the rule is the object key." } }, - "nullable": true, "metadata": { "description": "Optional. Outbound rules for the managed network of the workspace hub." } @@ -760,59 +778,68 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the user assigned identity for the AI Studio hub. If not provided, the hub will use a system assigned identity." + "description": "Optional. The name of the user-assigned identity for the AI Studio hub. If not provided, the hub will use a system-assigned identity." } }, "logAnalyticsConfiguration": { "$ref": "#/definitions/logAnalyticsConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the Log Analytics workspace." } }, "keyVaultConfiguration": { "$ref": "#/definitions/keyVaultConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the key vault." } }, "storageAccountConfiguration": { "$ref": "#/definitions/storageAccountConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the storage account." } }, "containerRegistryConfiguration": { "$ref": "#/definitions/containerRegistryConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the container registry." } }, "applicationInsightsConfiguration": { "$ref": "#/definitions/applicationInsightsConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for Application Insights." } }, "workspaceConfiguration": { "$ref": "#/definitions/workspaceConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the AI Studio workspace." } }, "virtualNetworkConfiguration": { "$ref": "#/definitions/virtualNetworkConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the virtual network." } }, "bastionConfiguration": { "$ref": "#/definitions/bastionConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the Azure Bastion host." } }, "virtualMachineConfiguration": { "$ref": "#/definitions/virtualMachineConfigurationType", + "nullable": true, "metadata": { "description": "Optional. Configuration for the virtual machine." } diff --git a/avm/ptn/azd/acr-container-app/main.json b/avm/ptn/azd/acr-container-app/main.json index 3aa2261a84..73927bb4fc 100644 --- a/avm/ptn/azd/acr-container-app/main.json +++ b/avm/ptn/azd/acr-container-app/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8683355263365484382" + "version": "0.30.23.60470", + "templateHash": "11200666829036307571" }, "name": "Azd ACR Linked Container App", "description": "Creates a container app in an Azure Container App environment.\n\n**Note:** This module is not intended for broad, generic use, as it was designed to cater for the requirements of the AZD CLI product. Feature requests and bug fix requests are welcome if they support the development of the AZD CLI but may not be incorporated if they aim to make this module more generic than what it needs to be for its primary use case", @@ -1428,8 +1428,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9239508313239206967" + "version": "0.30.23.60470", + "templateHash": "676465844790879977" }, "name": "ACR Pull permissions", "description": "Assigns ACR Pull permissions to access an Azure Container Registry.", @@ -1463,7 +1463,7 @@ { "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "acrpullrole-deployment", + "name": "[guid(subscription().id, resourceGroup().id, parameters('principalId'), variables('acrPullRole'))]", "properties": { "expressionEvaluationOptions": { "scope": "inner" diff --git a/avm/ptn/azd/acr-container-app/modules/registry-access.bicep b/avm/ptn/azd/acr-container-app/modules/registry-access.bicep index 3fdfe31799..33d6fd8ec6 100644 --- a/avm/ptn/azd/acr-container-app/modules/registry-access.bicep +++ b/avm/ptn/azd/acr-container-app/modules/registry-access.bicep @@ -17,7 +17,7 @@ var acrPullRole = subscriptionResourceId( ) module aksAcrPull 'br/public:avm/ptn/authorization/resource-role-assignment:0.1.1' = { - name: 'acrpullrole-deployment' + name: guid(subscription().id, resourceGroup().id, principalId, acrPullRole) params: { principalId: principalId resourceId: containerRegistry.id diff --git a/avm/ptn/azd/aks/README.md b/avm/ptn/azd/aks/README.md index 6e87179a15..be49729f45 100644 --- a/avm/ptn/azd/aks/README.md +++ b/avm/ptn/azd/aks/README.md @@ -65,7 +65,7 @@ module aks 'br/public:avm/ptn/azd/aks:' = { // Required parameters containerRegistryName: '' keyVaultName: '' - logAnalyticsName: '' + monitoringWorkspaceResourceId: '' name: '' principalId: '' // Non-required parameters @@ -94,8 +94,8 @@ module aks 'br/public:avm/ptn/azd/aks:' = { "keyVaultName": { "value": "" }, - "logAnalyticsName": { - "value": "" + "monitoringWorkspaceResourceId": { + "value": "" }, "name": { "value": "" @@ -127,7 +127,7 @@ using 'br/public:avm/ptn/azd/aks:' // Required parameters param containerRegistryName = '' param keyVaultName = '' -param logAnalyticsName = '' +param monitoringWorkspaceResourceId = '' param name = '' param principalId = '' // Non-required parameters @@ -154,12 +154,12 @@ module aks 'br/public:avm/ptn/azd/aks:' = { // Required parameters containerRegistryName: '' keyVaultName: '' - logAnalyticsName: '' + monitoringWorkspaceResourceId: '' name: '' principalId: '' // Non-required parameters acrSku: 'Basic' - agentPools: [ + agentPoolConfig: [ { maxPods: 30 maxSurge: '33%' @@ -167,15 +167,32 @@ module aks 'br/public:avm/ptn/azd/aks:' = { name: 'npuserpool' osType: 'Linux' type: 'VirtualMachineScaleSets' - vmSize: 'standard_a2_v2' + vmSize: 'Standard_DS2_v2' } ] + agentPoolSize: 'Standard' aksClusterRoleAssignmentName: '' containerRegistryRoleName: '' dnsPrefix: 'dep-dns-paamax' location: '' principalType: 'ServicePrincipal' skuTier: 'Free' + systemPoolConfig: [ + { + availabilityZones: [ + 1 + 2 + 3 + ] + count: 3 + enableAutoScaling: true + maxCount: 5 + minCount: 3 + mode: 'System' + name: 'npsystem' + vmSize: 'Standard_DS2_v2' + } + ] webApplicationRoutingEnabled: true } } @@ -200,8 +217,8 @@ module aks 'br/public:avm/ptn/azd/aks:' = { "keyVaultName": { "value": "" }, - "logAnalyticsName": { - "value": "" + "monitoringWorkspaceResourceId": { + "value": "" }, "name": { "value": "" @@ -213,7 +230,7 @@ module aks 'br/public:avm/ptn/azd/aks:' = { "acrSku": { "value": "Basic" }, - "agentPools": { + "agentPoolConfig": { "value": [ { "maxPods": 30, @@ -222,10 +239,13 @@ module aks 'br/public:avm/ptn/azd/aks:' = { "name": "npuserpool", "osType": "Linux", "type": "VirtualMachineScaleSets", - "vmSize": "standard_a2_v2" + "vmSize": "Standard_DS2_v2" } ] }, + "agentPoolSize": { + "value": "Standard" + }, "aksClusterRoleAssignmentName": { "value": "" }, @@ -244,6 +264,24 @@ module aks 'br/public:avm/ptn/azd/aks:' = { "skuTier": { "value": "Free" }, + "systemPoolConfig": { + "value": [ + { + "availabilityZones": [ + 1, + 2, + 3 + ], + "count": 3, + "enableAutoScaling": true, + "maxCount": 5, + "minCount": 3, + "mode": "System", + "name": "npsystem", + "vmSize": "Standard_DS2_v2" + } + ] + }, "webApplicationRoutingEnabled": { "value": true } @@ -264,12 +302,12 @@ using 'br/public:avm/ptn/azd/aks:' // Required parameters param containerRegistryName = '' param keyVaultName = '' -param logAnalyticsName = '' +param monitoringWorkspaceResourceId = '' param name = '' param principalId = '' // Non-required parameters param acrSku = 'Basic' -param agentPools = [ +param agentPoolConfig = [ { maxPods: 30 maxSurge: '33%' @@ -277,15 +315,32 @@ param agentPools = [ name: 'npuserpool' osType: 'Linux' type: 'VirtualMachineScaleSets' - vmSize: 'standard_a2_v2' + vmSize: 'Standard_DS2_v2' } ] +param agentPoolSize = 'Standard' param aksClusterRoleAssignmentName = '' param containerRegistryRoleName = '' param dnsPrefix = 'dep-dns-paamax' param location = '' param principalType = 'ServicePrincipal' param skuTier = 'Free' +param systemPoolConfig = [ + { + availabilityZones: [ + 1 + 2 + 3 + ] + count: 3 + enableAutoScaling: true + maxCount: 5 + minCount: 3 + mode: 'System' + name: 'npsystem' + vmSize: 'Standard_DS2_v2' + } +] param webApplicationRoutingEnabled = true ``` @@ -300,7 +355,7 @@ param webApplicationRoutingEnabled = true | :-- | :-- | :-- | | [`containerRegistryName`](#parameter-containerregistryname) | string | Name of your Azure Container Registry. | | [`keyVaultName`](#parameter-keyvaultname) | string | Name of the Key Vault. Must be globally unique. | -| [`logAnalyticsName`](#parameter-loganalyticsname) | string | The name of the connected log analytics workspace. | +| [`monitoringWorkspaceResourceId`](#parameter-monitoringworkspaceresourceid) | string | Resource ID of the monitoring log analytics workspace. | | [`name`](#parameter-name) | string | The name of the parent managed cluster. Required if the template is used in a standalone deployment. | | [`principalId`](#parameter-principalid) | string | Id of the user or app to assign application roles. | @@ -314,17 +369,24 @@ param webApplicationRoutingEnabled = true | Parameter | Type | Description | | :-- | :-- | :-- | -| [`aadProfileEnableAzureRBAC`](#parameter-aadprofileenableazurerbac) | bool | Specifies whether to enable Azure RBAC for Kubernetes authorization. | | [`acrSku`](#parameter-acrsku) | string | Tier of your Azure container registry. | -| [`agentPools`](#parameter-agentpools) | array | Define one or more secondary/additional agent pools. | +| [`agentPoolConfig`](#parameter-agentpoolconfig) | array | Custom configuration of user node pool. | +| [`agentPoolSize`](#parameter-agentpoolsize) | string | The User Pool Preset sizing. | | [`aksClusterRoleAssignmentName`](#parameter-aksclusterroleassignmentname) | string | The name (as GUID) of the role assignment. If not provided, a GUID will be generated. | +| [`autoNodeOsUpgradeProfileUpgradeChannel`](#parameter-autonodeosupgradeprofileupgradechannel) | string | Auto-upgrade channel on the Node Os. | | [`containerRegistryRoleName`](#parameter-containerregistryrolename) | string | The name (as GUID) of the role assignment. If not provided, a GUID will be generated. | +| [`disableLocalAccounts`](#parameter-disablelocalaccounts) | bool | 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. | | [`dnsPrefix`](#parameter-dnsprefix) | string | Specifies the DNS prefix specified when creating the managed cluster. | | [`dnsServiceIP`](#parameter-dnsserviceip) | string | Specifies the IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr. | +| [`enableKeyvaultSecretsProvider`](#parameter-enablekeyvaultsecretsprovider) | bool | Specifies whether the KeyvaultSecretsProvider add-on is enabled or not. | +| [`enablePurgeProtection`](#parameter-enablepurgeprotection) | bool | Provide 'true' to enable Key Vault's purge protection feature. | +| [`enableRbacAuthorization`](#parameter-enablerbacauthorization) | bool | 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. 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. Note that management actions are always authorized with RBAC. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`enableVaultForDeployment`](#parameter-enablevaultfordeployment) | bool | Specifies if the vault is enabled for deployment by script or compute. | +| [`enableVaultForTemplateDeployment`](#parameter-enablevaultfortemplatedeployment) | bool | Specifies if the vault is enabled for a template deployment. | | [`kubernetesVersion`](#parameter-kubernetesversion) | string | Kubernetes Version. | +| [`loadBalancerSku`](#parameter-loadbalancersku) | string | Specifies the sku of the load balancer used by the virtual machine scale sets used by nodepools. | | [`location`](#parameter-location) | string | Specifies the location of AKS cluster. It picks up Resource Group's location by default. | -| [`monitoringWorkspaceResourceId`](#parameter-monitoringworkspaceresourceid) | string | Resource ID of the monitoring log analytics workspace. | | [`networkDataplane`](#parameter-networkdataplane) | string | Network dataplane used in the Kubernetes cluster. Not compatible with kubenet network plugin. | | [`networkPlugin`](#parameter-networkplugin) | string | Network plugin used for building the Kubernetes network. | | [`networkPluginMode`](#parameter-networkpluginmode) | string | Network plugin mode used for building the Kubernetes network. Not compatible with kubenet network plugin. | @@ -337,6 +399,8 @@ param webApplicationRoutingEnabled = true | [`serviceCidr`](#parameter-servicecidr) | string | A CIDR notation IP range from which to assign service cluster IPs. It must not overlap with any Subnet IP ranges. | | [`skuTier`](#parameter-skutier) | string | Tier of a managed cluster SKU. | | [`sshPublicKey`](#parameter-sshpublickey) | string | Specifies the SSH RSA public key string for the Linux nodes. | +| [`systemPoolConfig`](#parameter-systempoolconfig) | array | Custom configuration of system node pool. | +| [`systemPoolSize`](#parameter-systempoolsize) | string | The System Pool Preset sizing. | | [`tags`](#parameter-tags) | object | Custom tags to apply to the AKS resources. | | [`webApplicationRoutingEnabled`](#parameter-webapplicationroutingenabled) | bool | Specifies whether the webApplicationRoutingEnabled add-on is enabled or not. | @@ -354,9 +418,9 @@ Name of the Key Vault. Must be globally unique. - Required: Yes - Type: string -### Parameter: `logAnalyticsName` +### Parameter: `monitoringWorkspaceResourceId` -The name of the connected log analytics workspace. +Resource ID of the monitoring log analytics workspace. - Required: Yes - Type: string @@ -382,14 +446,6 @@ Specifies the resource ID of connected application gateway. Required if `ingress - Required: No - Type: string -### Parameter: `aadProfileEnableAzureRBAC` - -Specifies whether to enable Azure RBAC for Kubernetes authorization. - -- Required: No -- Type: bool -- Default: `False` - ### Parameter: `acrSku` Tier of your Azure container registry. @@ -406,9 +462,9 @@ Tier of your Azure container registry. ] ``` -### Parameter: `agentPools` +### Parameter: `agentPoolConfig` -Define one or more secondary/additional agent pools. +Custom configuration of user node pool. - Required: No - Type: array @@ -417,113 +473,113 @@ Define one or more secondary/additional agent pools. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-agentpoolsname) | string | The name of the agent pool. | +| [`name`](#parameter-agentpoolconfigname) | string | The name of the agent pool. | **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | -| [`availabilityZones`](#parameter-agentpoolsavailabilityzones) | array | The availability zones of the agent pool. | -| [`count`](#parameter-agentpoolscount) | int | The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). | -| [`enableAutoScaling`](#parameter-agentpoolsenableautoscaling) | bool | Whether to enable auto-scaling for the agent pool. | -| [`enableDefaultTelemetry`](#parameter-agentpoolsenabledefaulttelemetry) | bool | The enable default telemetry of the agent pool. | -| [`enableEncryptionAtHost`](#parameter-agentpoolsenableencryptionathost) | bool | Whether to enable encryption at host for the agent pool. | -| [`enableFIPS`](#parameter-agentpoolsenablefips) | bool | Whether to enable FIPS for the agent pool. | -| [`enableNodePublicIP`](#parameter-agentpoolsenablenodepublicip) | bool | Whether to enable node public IP for the agent pool. | -| [`enableUltraSSD`](#parameter-agentpoolsenableultrassd) | bool | Whether to enable Ultra SSD for the agent pool. | -| [`gpuInstanceProfile`](#parameter-agentpoolsgpuinstanceprofile) | string | The GPU instance profile of the agent pool. | -| [`kubeletDiskType`](#parameter-agentpoolskubeletdisktype) | string | The kubelet disk type of the agent pool. | -| [`maxCount`](#parameter-agentpoolsmaxcount) | int | The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). | -| [`maxPods`](#parameter-agentpoolsmaxpods) | int | The maximum number of pods that can run on a node. | -| [`maxSurge`](#parameter-agentpoolsmaxsurge) | string | The maximum number of nodes that can be created during an upgrade. | -| [`minCount`](#parameter-agentpoolsmincount) | int | The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). | -| [`minPods`](#parameter-agentpoolsminpods) | int | The minimum number of pods that can run on a node. | -| [`mode`](#parameter-agentpoolsmode) | string | The mode of the agent pool. | -| [`nodeLabels`](#parameter-agentpoolsnodelabels) | object | The node labels of the agent pool. | -| [`nodePublicIpPrefixId`](#parameter-agentpoolsnodepublicipprefixid) | string | The node public IP prefix ID of the agent pool. | -| [`nodeTaints`](#parameter-agentpoolsnodetaints) | array | The node taints of the agent pool. | -| [`orchestratorVersion`](#parameter-agentpoolsorchestratorversion) | string | The Kubernetes version of the agent pool. | -| [`osDiskSizeGB`](#parameter-agentpoolsosdisksizegb) | int | The OS disk size in GB of the agent pool. | -| [`osDiskType`](#parameter-agentpoolsosdisktype) | string | The OS disk type of the agent pool. | -| [`osSku`](#parameter-agentpoolsossku) | string | The OS SKU of the agent pool. | -| [`osType`](#parameter-agentpoolsostype) | string | The OS type of the agent pool. | -| [`podSubnetId`](#parameter-agentpoolspodsubnetid) | string | The pod subnet ID of the agent pool. | -| [`proximityPlacementGroupResourceId`](#parameter-agentpoolsproximityplacementgroupresourceid) | string | The proximity placement group resource ID of the agent pool. | -| [`scaleDownMode`](#parameter-agentpoolsscaledownmode) | string | The scale down mode of the agent pool. | -| [`scaleSetEvictionPolicy`](#parameter-agentpoolsscalesetevictionpolicy) | string | The scale set eviction policy of the agent pool. | -| [`scaleSetPriority`](#parameter-agentpoolsscalesetpriority) | string | The scale set priority of the agent pool. | -| [`sourceResourceId`](#parameter-agentpoolssourceresourceid) | string | The source resource ID to create the agent pool from. | -| [`spotMaxPrice`](#parameter-agentpoolsspotmaxprice) | int | The spot max price of the agent pool. | -| [`tags`](#parameter-agentpoolstags) | object | The tags of the agent pool. | -| [`type`](#parameter-agentpoolstype) | string | The type of the agent pool. | -| [`vmSize`](#parameter-agentpoolsvmsize) | string | The VM size of the agent pool. | -| [`vnetSubnetID`](#parameter-agentpoolsvnetsubnetid) | string | The VNet subnet ID of the agent pool. | -| [`workloadRuntime`](#parameter-agentpoolsworkloadruntime) | string | The workload runtime of the agent pool. | - -### Parameter: `agentPools.name` +| [`availabilityZones`](#parameter-agentpoolconfigavailabilityzones) | array | The availability zones of the agent pool. | +| [`count`](#parameter-agentpoolconfigcount) | int | The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). | +| [`enableAutoScaling`](#parameter-agentpoolconfigenableautoscaling) | bool | Whether to enable auto-scaling for the agent pool. | +| [`enableDefaultTelemetry`](#parameter-agentpoolconfigenabledefaulttelemetry) | bool | The enable default telemetry of the agent pool. | +| [`enableEncryptionAtHost`](#parameter-agentpoolconfigenableencryptionathost) | bool | Whether to enable encryption at host for the agent pool. | +| [`enableFIPS`](#parameter-agentpoolconfigenablefips) | bool | Whether to enable FIPS for the agent pool. | +| [`enableNodePublicIP`](#parameter-agentpoolconfigenablenodepublicip) | bool | Whether to enable node public IP for the agent pool. | +| [`enableUltraSSD`](#parameter-agentpoolconfigenableultrassd) | bool | Whether to enable Ultra SSD for the agent pool. | +| [`gpuInstanceProfile`](#parameter-agentpoolconfiggpuinstanceprofile) | string | The GPU instance profile of the agent pool. | +| [`kubeletDiskType`](#parameter-agentpoolconfigkubeletdisktype) | string | The kubelet disk type of the agent pool. | +| [`maxCount`](#parameter-agentpoolconfigmaxcount) | int | The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). | +| [`maxPods`](#parameter-agentpoolconfigmaxpods) | int | The maximum number of pods that can run on a node. | +| [`maxSurge`](#parameter-agentpoolconfigmaxsurge) | string | The maximum number of nodes that can be created during an upgrade. | +| [`minCount`](#parameter-agentpoolconfigmincount) | int | The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). | +| [`minPods`](#parameter-agentpoolconfigminpods) | int | The minimum number of pods that can run on a node. | +| [`mode`](#parameter-agentpoolconfigmode) | string | The mode of the agent pool. | +| [`nodeLabels`](#parameter-agentpoolconfignodelabels) | object | The node labels of the agent pool. | +| [`nodePublicIpPrefixResourceId`](#parameter-agentpoolconfignodepublicipprefixresourceid) | string | The node public IP prefix ID of the agent pool. | +| [`nodeTaints`](#parameter-agentpoolconfignodetaints) | array | The node taints of the agent pool. | +| [`orchestratorVersion`](#parameter-agentpoolconfigorchestratorversion) | string | The Kubernetes version of the agent pool. | +| [`osDiskSizeGB`](#parameter-agentpoolconfigosdisksizegb) | int | The OS disk size in GB of the agent pool. | +| [`osDiskType`](#parameter-agentpoolconfigosdisktype) | string | The OS disk type of the agent pool. | +| [`osSku`](#parameter-agentpoolconfigossku) | string | The OS SKU of the agent pool. | +| [`osType`](#parameter-agentpoolconfigostype) | string | The OS type of the agent pool. | +| [`podSubnetResourceId`](#parameter-agentpoolconfigpodsubnetresourceid) | string | The pod subnet ID of the agent pool. | +| [`proximityPlacementGroupResourceId`](#parameter-agentpoolconfigproximityplacementgroupresourceid) | string | The proximity placement group resource ID of the agent pool. | +| [`scaleDownMode`](#parameter-agentpoolconfigscaledownmode) | string | The scale down mode of the agent pool. | +| [`scaleSetEvictionPolicy`](#parameter-agentpoolconfigscalesetevictionpolicy) | string | The scale set eviction policy of the agent pool. | +| [`scaleSetPriority`](#parameter-agentpoolconfigscalesetpriority) | string | The scale set priority of the agent pool. | +| [`sourceResourceId`](#parameter-agentpoolconfigsourceresourceid) | string | The source resource ID to create the agent pool from. | +| [`spotMaxPrice`](#parameter-agentpoolconfigspotmaxprice) | int | The spot max price of the agent pool. | +| [`tags`](#parameter-agentpoolconfigtags) | object | The tags of the agent pool. | +| [`type`](#parameter-agentpoolconfigtype) | string | The type of the agent pool. | +| [`vmSize`](#parameter-agentpoolconfigvmsize) | string | The VM size of the agent pool. | +| [`vnetSubnetResourceId`](#parameter-agentpoolconfigvnetsubnetresourceid) | string | The VNet subnet ID of the agent pool. | +| [`workloadRuntime`](#parameter-agentpoolconfigworkloadruntime) | string | The workload runtime of the agent pool. | + +### Parameter: `agentPoolConfig.name` The name of the agent pool. - Required: Yes - Type: string -### Parameter: `agentPools.availabilityZones` +### Parameter: `agentPoolConfig.availabilityZones` The availability zones of the agent pool. - Required: No - Type: array -### Parameter: `agentPools.count` +### Parameter: `agentPoolConfig.count` The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). - Required: No - Type: int -### Parameter: `agentPools.enableAutoScaling` +### Parameter: `agentPoolConfig.enableAutoScaling` Whether to enable auto-scaling for the agent pool. - Required: No - Type: bool -### Parameter: `agentPools.enableDefaultTelemetry` +### Parameter: `agentPoolConfig.enableDefaultTelemetry` The enable default telemetry of the agent pool. - Required: No - Type: bool -### Parameter: `agentPools.enableEncryptionAtHost` +### Parameter: `agentPoolConfig.enableEncryptionAtHost` Whether to enable encryption at host for the agent pool. - Required: No - Type: bool -### Parameter: `agentPools.enableFIPS` +### Parameter: `agentPoolConfig.enableFIPS` Whether to enable FIPS for the agent pool. - Required: No - Type: bool -### Parameter: `agentPools.enableNodePublicIP` +### Parameter: `agentPoolConfig.enableNodePublicIP` Whether to enable node public IP for the agent pool. - Required: No - Type: bool -### Parameter: `agentPools.enableUltraSSD` +### Parameter: `agentPoolConfig.enableUltraSSD` Whether to enable Ultra SSD for the agent pool. - Required: No - Type: bool -### Parameter: `agentPools.gpuInstanceProfile` +### Parameter: `agentPoolConfig.gpuInstanceProfile` The GPU instance profile of the agent pool. @@ -540,49 +596,49 @@ The GPU instance profile of the agent pool. ] ``` -### Parameter: `agentPools.kubeletDiskType` +### Parameter: `agentPoolConfig.kubeletDiskType` The kubelet disk type of the agent pool. - Required: No - Type: string -### Parameter: `agentPools.maxCount` +### Parameter: `agentPoolConfig.maxCount` The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). - Required: No - Type: int -### Parameter: `agentPools.maxPods` +### Parameter: `agentPoolConfig.maxPods` The maximum number of pods that can run on a node. - Required: No - Type: int -### Parameter: `agentPools.maxSurge` +### Parameter: `agentPoolConfig.maxSurge` The maximum number of nodes that can be created during an upgrade. - Required: No - Type: string -### Parameter: `agentPools.minCount` +### Parameter: `agentPoolConfig.minCount` The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). - Required: No - Type: int -### Parameter: `agentPools.minPods` +### Parameter: `agentPoolConfig.minPods` The minimum number of pods that can run on a node. - Required: No - Type: int -### Parameter: `agentPools.mode` +### Parameter: `agentPoolConfig.mode` The mode of the agent pool. @@ -596,56 +652,56 @@ The mode of the agent pool. ] ``` -### Parameter: `agentPools.nodeLabels` +### Parameter: `agentPoolConfig.nodeLabels` The node labels of the agent pool. - Required: No - Type: object -### Parameter: `agentPools.nodePublicIpPrefixId` +### Parameter: `agentPoolConfig.nodePublicIpPrefixResourceId` The node public IP prefix ID of the agent pool. - Required: No - Type: string -### Parameter: `agentPools.nodeTaints` +### Parameter: `agentPoolConfig.nodeTaints` The node taints of the agent pool. - Required: No - Type: array -### Parameter: `agentPools.orchestratorVersion` +### Parameter: `agentPoolConfig.orchestratorVersion` The Kubernetes version of the agent pool. - Required: No - Type: string -### Parameter: `agentPools.osDiskSizeGB` +### Parameter: `agentPoolConfig.osDiskSizeGB` The OS disk size in GB of the agent pool. - Required: No - Type: int -### Parameter: `agentPools.osDiskType` +### Parameter: `agentPoolConfig.osDiskType` The OS disk type of the agent pool. - Required: No - Type: string -### Parameter: `agentPools.osSku` +### Parameter: `agentPoolConfig.osSku` The OS SKU of the agent pool. - Required: No - Type: string -### Parameter: `agentPools.osType` +### Parameter: `agentPoolConfig.osType` The OS type of the agent pool. @@ -659,21 +715,21 @@ The OS type of the agent pool. ] ``` -### Parameter: `agentPools.podSubnetId` +### Parameter: `agentPoolConfig.podSubnetResourceId` The pod subnet ID of the agent pool. - Required: No - Type: string -### Parameter: `agentPools.proximityPlacementGroupResourceId` +### Parameter: `agentPoolConfig.proximityPlacementGroupResourceId` The proximity placement group resource ID of the agent pool. - Required: No - Type: string -### Parameter: `agentPools.scaleDownMode` +### Parameter: `agentPoolConfig.scaleDownMode` The scale down mode of the agent pool. @@ -687,7 +743,7 @@ The scale down mode of the agent pool. ] ``` -### Parameter: `agentPools.scaleSetEvictionPolicy` +### Parameter: `agentPoolConfig.scaleSetEvictionPolicy` The scale set eviction policy of the agent pool. @@ -701,7 +757,7 @@ The scale set eviction policy of the agent pool. ] ``` -### Parameter: `agentPools.scaleSetPriority` +### Parameter: `agentPoolConfig.scaleSetPriority` The scale set priority of the agent pool. @@ -716,28 +772,28 @@ The scale set priority of the agent pool. ] ``` -### Parameter: `agentPools.sourceResourceId` +### Parameter: `agentPoolConfig.sourceResourceId` The source resource ID to create the agent pool from. - Required: No - Type: string -### Parameter: `agentPools.spotMaxPrice` +### Parameter: `agentPoolConfig.spotMaxPrice` The spot max price of the agent pool. - Required: No - Type: int -### Parameter: `agentPools.tags` +### Parameter: `agentPoolConfig.tags` The tags of the agent pool. - Required: No - Type: object -### Parameter: `agentPools.type` +### Parameter: `agentPoolConfig.type` The type of the agent pool. @@ -751,27 +807,45 @@ The type of the agent pool. ] ``` -### Parameter: `agentPools.vmSize` +### Parameter: `agentPoolConfig.vmSize` The VM size of the agent pool. - Required: No - Type: string -### Parameter: `agentPools.vnetSubnetID` +### Parameter: `agentPoolConfig.vnetSubnetResourceId` The VNet subnet ID of the agent pool. - Required: No - Type: string -### Parameter: `agentPools.workloadRuntime` +### Parameter: `agentPoolConfig.workloadRuntime` The workload runtime of the agent pool. - Required: No - Type: string +### Parameter: `agentPoolSize` + +The User Pool Preset sizing. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'CostOptimised' + 'Custom' + 'HighSpec' + 'Standard' + ] + ``` + ### Parameter: `aksClusterRoleAssignmentName` The name (as GUID) of the role assignment. If not provided, a GUID will be generated. @@ -779,6 +853,23 @@ The name (as GUID) of the role assignment. If not provided, a GUID will be gener - Required: No - Type: string +### Parameter: `autoNodeOsUpgradeProfileUpgradeChannel` + +Auto-upgrade channel on the Node Os. + +- Required: No +- Type: string +- Default: `'NodeImage'` +- Allowed: + ```Bicep + [ + 'NodeImage' + 'None' + 'SecurityPatch' + 'Unmanaged' + ] + ``` + ### Parameter: `containerRegistryRoleName` The name (as GUID) of the role assignment. If not provided, a GUID will be generated. @@ -786,6 +877,14 @@ The name (as GUID) of the role assignment. If not provided, a GUID will be gener - Required: No - Type: string +### Parameter: `disableLocalAccounts` + +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. + +- Required: No +- Type: bool +- Default: `True` + ### Parameter: `dnsPrefix` Specifies the DNS prefix specified when creating the managed cluster. @@ -801,6 +900,30 @@ Specifies the IP address assigned to the Kubernetes DNS service. It must be with - Required: No - Type: string +### Parameter: `enableKeyvaultSecretsProvider` + +Specifies whether the KeyvaultSecretsProvider add-on is enabled or not. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `enablePurgeProtection` + +Provide 'true' to enable Key Vault's purge protection feature. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableRbacAuthorization` + +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. 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. Note that management actions are always authorized with RBAC. + +- Required: No +- Type: bool +- Default: `False` + ### Parameter: `enableTelemetry` Enable/Disable usage telemetry for module. @@ -809,6 +932,22 @@ Enable/Disable usage telemetry for module. - Type: bool - Default: `True` +### Parameter: `enableVaultForDeployment` + +Specifies if the vault is enabled for deployment by script or compute. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableVaultForTemplateDeployment` + +Specifies if the vault is enabled for a template deployment. + +- Required: No +- Type: bool +- Default: `False` + ### Parameter: `kubernetesVersion` Kubernetes Version. @@ -817,20 +956,28 @@ Kubernetes Version. - Type: string - Default: `'1.29'` -### Parameter: `location` +### Parameter: `loadBalancerSku` -Specifies the location of AKS cluster. It picks up Resource Group's location by default. +Specifies the sku of the load balancer used by the virtual machine scale sets used by nodepools. - Required: No - Type: string -- Default: `[resourceGroup().location]` +- Default: `'standard'` +- Allowed: + ```Bicep + [ + 'basic' + 'standard' + ] + ``` -### Parameter: `monitoringWorkspaceResourceId` +### Parameter: `location` -Resource ID of the monitoring log analytics workspace. +Specifies the location of AKS cluster. It picks up Resource Group's location by default. - Required: No - Type: string +- Default: `[resourceGroup().location]` ### Parameter: `networkDataplane` @@ -1008,6 +1155,389 @@ Specifies the SSH RSA public key string for the Linux nodes. - Required: No - Type: string +### Parameter: `systemPoolConfig` + +Custom configuration of system node pool. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-systempoolconfigname) | string | The name of the agent pool. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`availabilityZones`](#parameter-systempoolconfigavailabilityzones) | array | The availability zones of the agent pool. | +| [`count`](#parameter-systempoolconfigcount) | int | The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). | +| [`enableAutoScaling`](#parameter-systempoolconfigenableautoscaling) | bool | Whether to enable auto-scaling for the agent pool. | +| [`enableDefaultTelemetry`](#parameter-systempoolconfigenabledefaulttelemetry) | bool | The enable default telemetry of the agent pool. | +| [`enableEncryptionAtHost`](#parameter-systempoolconfigenableencryptionathost) | bool | Whether to enable encryption at host for the agent pool. | +| [`enableFIPS`](#parameter-systempoolconfigenablefips) | bool | Whether to enable FIPS for the agent pool. | +| [`enableNodePublicIP`](#parameter-systempoolconfigenablenodepublicip) | bool | Whether to enable node public IP for the agent pool. | +| [`enableUltraSSD`](#parameter-systempoolconfigenableultrassd) | bool | Whether to enable Ultra SSD for the agent pool. | +| [`gpuInstanceProfile`](#parameter-systempoolconfiggpuinstanceprofile) | string | The GPU instance profile of the agent pool. | +| [`kubeletDiskType`](#parameter-systempoolconfigkubeletdisktype) | string | The kubelet disk type of the agent pool. | +| [`maxCount`](#parameter-systempoolconfigmaxcount) | int | The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). | +| [`maxPods`](#parameter-systempoolconfigmaxpods) | int | The maximum number of pods that can run on a node. | +| [`maxSurge`](#parameter-systempoolconfigmaxsurge) | string | The maximum number of nodes that can be created during an upgrade. | +| [`minCount`](#parameter-systempoolconfigmincount) | int | The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). | +| [`minPods`](#parameter-systempoolconfigminpods) | int | The minimum number of pods that can run on a node. | +| [`mode`](#parameter-systempoolconfigmode) | string | The mode of the agent pool. | +| [`nodeLabels`](#parameter-systempoolconfignodelabels) | object | The node labels of the agent pool. | +| [`nodePublicIpPrefixResourceId`](#parameter-systempoolconfignodepublicipprefixresourceid) | string | The node public IP prefix ID of the agent pool. | +| [`nodeTaints`](#parameter-systempoolconfignodetaints) | array | The node taints of the agent pool. | +| [`orchestratorVersion`](#parameter-systempoolconfigorchestratorversion) | string | The Kubernetes version of the agent pool. | +| [`osDiskSizeGB`](#parameter-systempoolconfigosdisksizegb) | int | The OS disk size in GB of the agent pool. | +| [`osDiskType`](#parameter-systempoolconfigosdisktype) | string | The OS disk type of the agent pool. | +| [`osSku`](#parameter-systempoolconfigossku) | string | The OS SKU of the agent pool. | +| [`osType`](#parameter-systempoolconfigostype) | string | The OS type of the agent pool. | +| [`podSubnetResourceId`](#parameter-systempoolconfigpodsubnetresourceid) | string | The pod subnet ID of the agent pool. | +| [`proximityPlacementGroupResourceId`](#parameter-systempoolconfigproximityplacementgroupresourceid) | string | The proximity placement group resource ID of the agent pool. | +| [`scaleDownMode`](#parameter-systempoolconfigscaledownmode) | string | The scale down mode of the agent pool. | +| [`scaleSetEvictionPolicy`](#parameter-systempoolconfigscalesetevictionpolicy) | string | The scale set eviction policy of the agent pool. | +| [`scaleSetPriority`](#parameter-systempoolconfigscalesetpriority) | string | The scale set priority of the agent pool. | +| [`sourceResourceId`](#parameter-systempoolconfigsourceresourceid) | string | The source resource ID to create the agent pool from. | +| [`spotMaxPrice`](#parameter-systempoolconfigspotmaxprice) | int | The spot max price of the agent pool. | +| [`tags`](#parameter-systempoolconfigtags) | object | The tags of the agent pool. | +| [`type`](#parameter-systempoolconfigtype) | string | The type of the agent pool. | +| [`vmSize`](#parameter-systempoolconfigvmsize) | string | The VM size of the agent pool. | +| [`vnetSubnetResourceId`](#parameter-systempoolconfigvnetsubnetresourceid) | string | The VNet subnet ID of the agent pool. | +| [`workloadRuntime`](#parameter-systempoolconfigworkloadruntime) | string | The workload runtime of the agent pool. | + +### Parameter: `systemPoolConfig.name` + +The name of the agent pool. + +- Required: Yes +- Type: string + +### Parameter: `systemPoolConfig.availabilityZones` + +The availability zones of the agent pool. + +- Required: No +- Type: array + +### Parameter: `systemPoolConfig.count` + +The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). + +- Required: No +- Type: int + +### Parameter: `systemPoolConfig.enableAutoScaling` + +Whether to enable auto-scaling for the agent pool. + +- Required: No +- Type: bool + +### Parameter: `systemPoolConfig.enableDefaultTelemetry` + +The enable default telemetry of the agent pool. + +- Required: No +- Type: bool + +### Parameter: `systemPoolConfig.enableEncryptionAtHost` + +Whether to enable encryption at host for the agent pool. + +- Required: No +- Type: bool + +### Parameter: `systemPoolConfig.enableFIPS` + +Whether to enable FIPS for the agent pool. + +- Required: No +- Type: bool + +### Parameter: `systemPoolConfig.enableNodePublicIP` + +Whether to enable node public IP for the agent pool. + +- Required: No +- Type: bool + +### Parameter: `systemPoolConfig.enableUltraSSD` + +Whether to enable Ultra SSD for the agent pool. + +- Required: No +- Type: bool + +### Parameter: `systemPoolConfig.gpuInstanceProfile` + +The GPU instance profile of the agent pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'MIG1g' + 'MIG2g' + 'MIG3g' + 'MIG4g' + 'MIG7g' + ] + ``` + +### Parameter: `systemPoolConfig.kubeletDiskType` + +The kubelet disk type of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.maxCount` + +The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). + +- Required: No +- Type: int + +### Parameter: `systemPoolConfig.maxPods` + +The maximum number of pods that can run on a node. + +- Required: No +- Type: int + +### Parameter: `systemPoolConfig.maxSurge` + +The maximum number of nodes that can be created during an upgrade. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.minCount` + +The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive). + +- Required: No +- Type: int + +### Parameter: `systemPoolConfig.minPods` + +The minimum number of pods that can run on a node. + +- Required: No +- Type: int + +### Parameter: `systemPoolConfig.mode` + +The mode of the agent pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'System' + 'User' + ] + ``` + +### Parameter: `systemPoolConfig.nodeLabels` + +The node labels of the agent pool. + +- Required: No +- Type: object + +### Parameter: `systemPoolConfig.nodePublicIpPrefixResourceId` + +The node public IP prefix ID of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.nodeTaints` + +The node taints of the agent pool. + +- Required: No +- Type: array + +### Parameter: `systemPoolConfig.orchestratorVersion` + +The Kubernetes version of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.osDiskSizeGB` + +The OS disk size in GB of the agent pool. + +- Required: No +- Type: int + +### Parameter: `systemPoolConfig.osDiskType` + +The OS disk type of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.osSku` + +The OS SKU of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.osType` + +The OS type of the agent pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Linux' + 'Windows' + ] + ``` + +### Parameter: `systemPoolConfig.podSubnetResourceId` + +The pod subnet ID of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.proximityPlacementGroupResourceId` + +The proximity placement group resource ID of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.scaleDownMode` + +The scale down mode of the agent pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Deallocate' + 'Delete' + ] + ``` + +### Parameter: `systemPoolConfig.scaleSetEvictionPolicy` + +The scale set eviction policy of the agent pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Deallocate' + 'Delete' + ] + ``` + +### Parameter: `systemPoolConfig.scaleSetPriority` + +The scale set priority of the agent pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Low' + 'Regular' + 'Spot' + ] + ``` + +### Parameter: `systemPoolConfig.sourceResourceId` + +The source resource ID to create the agent pool from. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.spotMaxPrice` + +The spot max price of the agent pool. + +- Required: No +- Type: int + +### Parameter: `systemPoolConfig.tags` + +The tags of the agent pool. + +- Required: No +- Type: object + +### Parameter: `systemPoolConfig.type` + +The type of the agent pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AvailabilitySet' + 'VirtualMachineScaleSets' + ] + ``` + +### Parameter: `systemPoolConfig.vmSize` + +The VM size of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.vnetSubnetResourceId` + +The VNet subnet ID of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolConfig.workloadRuntime` + +The workload runtime of the agent pool. + +- Required: No +- Type: string + +### Parameter: `systemPoolSize` + +The System Pool Preset sizing. + +- Required: No +- Type: string +- Default: `'Standard'` +- Allowed: + ```Bicep + [ + 'CostOptimised' + 'Custom' + 'HighSpec' + 'Standard' + ] + ``` + ### Parameter: `tags` Custom tags to apply to the AKS resources. @@ -1022,6 +1552,7 @@ Specifies whether the webApplicationRoutingEnabled add-on is enabled or not. - Required: No - Type: bool +- Default: `True` ## Outputs @@ -1042,7 +1573,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/container-registry/registry:0.5.1` | Remote reference | -| `br/public:avm/res/container-service/managed-cluster:0.3.0` | Remote reference | +| `br/public:avm/res/container-service/managed-cluster:0.4.1` | Remote reference | | `br/public:avm/res/key-vault/vault:0.9.0` | Remote reference | ## Data Collection diff --git a/avm/ptn/azd/aks/main.bicep b/avm/ptn/azd/aks/main.bicep index de942be0ab..6ca5ee2d38 100644 --- a/avm/ptn/azd/aks/main.bicep +++ b/avm/ptn/azd/aks/main.bicep @@ -12,9 +12,6 @@ param name string @maxLength(50) param containerRegistryName string -@description('Required. The name of the connected log analytics workspace.') -param logAnalyticsName string - @description('Required. Name of the Key Vault. Must be globally unique.') @maxLength(24) param keyVaultName string @@ -85,17 +82,11 @@ param dnsServiceIP string? @description('Optional. Specifies the SSH RSA public key string for the Linux nodes.') param sshPublicKey string? -@description('Optional. Specifies whether to enable Azure RBAC for Kubernetes authorization.') -param aadProfileEnableAzureRBAC bool = false - @description('Conditional. Specifies the resource ID of connected application gateway. Required if `ingressApplicationGatewayEnabled` is set to `true`.') param appGatewayResourceId string? -@description('Optional. Resource ID of the monitoring log analytics workspace.') -param monitoringWorkspaceResourceId string? - -@description('Optional. Define one or more secondary/additional agent pools.') -param agentPools agentPoolType +@description('Required. Resource ID of the monitoring log analytics workspace.') +param monitoringWorkspaceResourceId string @description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and networkRuleSetIpRules are not set. Note, requires the \'acrSku\' to be \'Premium\'.') @allowed([ @@ -104,11 +95,18 @@ param agentPools agentPoolType ]) param publicNetworkAccess string = 'Enabled' +@description('Optional. Specifies the sku of the load balancer used by the virtual machine scale sets used by nodepools.') +@allowed([ + 'basic' + 'standard' +]) +param loadBalancerSku string = 'standard' + @description('Optional. Scope maps setting.') param scopeMaps scopeMapsType @description('Optional. Specifies whether the webApplicationRoutingEnabled add-on is enabled or not.') -param webApplicationRoutingEnabled bool? +param webApplicationRoutingEnabled bool = true @description('Optional. Tier of your Azure container registry.') @allowed([ @@ -124,6 +122,63 @@ param containerRegistryRoleName string? @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') param aksClusterRoleAssignmentName string? +import {agentPoolType} from 'br/public:avm/res/container-service/managed-cluster:0.4.1' +@description('Optional. Custom configuration of system node pool.') +param systemPoolConfig agentPoolType[]? + +@description('Optional. Custom configuration of user node pool.') +param agentPoolConfig agentPoolType[]? + +@description('Optional. Specifies whether the KeyvaultSecretsProvider add-on is enabled or not.') +param enableKeyvaultSecretsProvider 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 = true + +@allowed([ + 'NodeImage' + 'None' + 'SecurityPatch' + 'Unmanaged' +]) +@description('Optional. Auto-upgrade channel on the Node Os.') +param autoNodeOsUpgradeProfileUpgradeChannel string = 'NodeImage' + +@allowed([ + 'CostOptimised' + 'Standard' + 'HighSpec' + 'Custom' +]) +@description('Optional. The System Pool Preset sizing.') +param systemPoolSize string = 'Standard' + +@allowed([ + '' + 'CostOptimised' + 'Standard' + 'HighSpec' + 'Custom' +]) +@description('Optional. The User Pool Preset sizing.') +param agentPoolSize string = '' + +@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. 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. Note that management actions are always authorized with RBAC.') +param enableRbacAuthorization bool = false + +@description('Optional. Provide \'true\' to enable Key Vault\'s purge protection feature.') +param enablePurgeProtection bool = false + +@description('Optional. Specifies if the vault is enabled for deployment by script or compute.') +param enableVaultForDeployment bool = false + +@description('Optional. Specifies if the vault is enabled for a template deployment.') +param enableVaultForTemplateDeployment bool = false + +var systemPoolsConfig = !empty(systemPoolConfig) ? systemPoolConfig : [union({ name: 'npsystem', mode: 'System' }, nodePoolBase, nodePoolPresets[systemPoolSize])] + +var agentPoolsConfig = !empty(agentPoolConfig) ? agentPoolConfig : empty(agentPoolSize) ? null : [union({ name: 'npuser', mode: 'User' }, nodePoolBase, nodePoolPresets[agentPoolSize])] + var aksClusterAdminRole = subscriptionResourceId( 'Microsoft.Authorization/roleDefinitions', 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' @@ -135,16 +190,38 @@ var acrPullRole = subscriptionResourceId( ) var nodePoolPresets = { - vmSize: 'Standard_DS2_v2' - count: 3 - minCount: 3 - maxCount: 5 - enableAutoScaling: true - availabilityZones: [ - '1' - '2' - '3' - ] + CostOptimised: { + vmSize: 'Standard_B4ms' + count: 1 + minCount: 1 + maxCount: 3 + enableAutoScaling: true + availabilityZones: [] + } + Standard: { + vmSize: 'Standard_DS2_v2' + count: 3 + minCount: 3 + maxCount: 5 + enableAutoScaling: true + availabilityZones: [ + 1 + 2 + 3 + ] + } + HighSpec: { + vmSize: 'Standard_D4s_v3' + count: 3 + minCount: 3 + maxCount: 5 + enableAutoScaling: true + availabilityZones: [ + '1' + '2' + '3' + ] + } } var nodePoolBase = { @@ -156,10 +233,6 @@ var nodePoolBase = { } } -var primaryAgentPoolProfile = [ - union({ name: 'npsystem', mode: 'System' }, nodePoolBase, nodePoolPresets) -] - // ============== // // Resources // // ============== // @@ -183,11 +256,7 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableT } } -resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' existing = if (!empty(logAnalyticsName)) { - name: logAnalyticsName -} - -module managedCluster 'br/public:avm/res/container-service/managed-cluster:0.3.0' = { +module managedCluster 'br/public:avm/res/container-service/managed-cluster:0.4.1' = { name: '${uniqueString(deployment().name, location)}-managed-cluster' params: { name: name @@ -203,10 +272,15 @@ module managedCluster 'br/public:avm/res/container-service/managed-cluster:0.3.0 dnsServiceIP: dnsServiceIP kubernetesVersion: kubernetesVersion sshPublicKey: sshPublicKey - aadProfileEnableAzureRBAC: aadProfileEnableAzureRBAC skuTier: skuTier appGatewayResourceId: appGatewayResourceId - monitoringWorkspaceId: monitoringWorkspaceResourceId + monitoringWorkspaceResourceId: monitoringWorkspaceResourceId + publicNetworkAccess: publicNetworkAccess + autoNodeOsUpgradeProfileUpgradeChannel: autoNodeOsUpgradeProfileUpgradeChannel + enableKeyvaultSecretsProvider: enableKeyvaultSecretsProvider + webApplicationRoutingEnabled: webApplicationRoutingEnabled + disableLocalAccounts: disableLocalAccounts + loadBalancerSku: loadBalancerSku managedIdentities: { systemAssigned: true } @@ -230,7 +304,7 @@ module managedCluster 'br/public:avm/res/container-service/managed-cluster:0.3.0 enabled: true } ] - workspaceResourceId: !empty(logAnalyticsName) ? logAnalytics.id : '' + workspaceResourceId: monitoringWorkspaceResourceId metricCategories: [ { category: 'AllMetrics' @@ -239,10 +313,9 @@ module managedCluster 'br/public:avm/res/container-service/managed-cluster:0.3.0 ] } ] - webApplicationRoutingEnabled: webApplicationRoutingEnabled - primaryAgentPoolProfile: primaryAgentPoolProfile + primaryAgentPoolProfiles: systemPoolsConfig dnsPrefix: dnsPrefix - agentPools: agentPools + agentPools: agentPoolsConfig enableTelemetry: enableTelemetry roleAssignments: [ { @@ -277,7 +350,7 @@ module containerRegistry 'br/public:avm/res/container-registry/registry:0.5.1' = enabled: true } ] - workspaceResourceId: !empty(logAnalyticsName) ? logAnalytics.id : '' + workspaceResourceId: monitoringWorkspaceResourceId metricCategories: [ { category: 'AllMetrics' @@ -301,6 +374,10 @@ module keyVault 'br/public:avm/res/key-vault/vault:0.9.0' = { params: { name: keyVaultName enableTelemetry: enableTelemetry + enableRbacAuthorization: enableRbacAuthorization + enableVaultForDeployment: enableVaultForDeployment + enableVaultForTemplateDeployment: enableVaultForTemplateDeployment + enablePurgeProtection: enablePurgeProtection accessPolicies: [ { objectId: managedCluster.outputs.kubeletIdentityObjectId @@ -341,119 +418,6 @@ output containerRegistryLoginServer string = containerRegistry.outputs.loginServ // Definitions // // =============== // -type agentPoolType = { - @description('Required. The name of the agent pool.') - name: string - - @description('Optional. The availability zones of the agent pool.') - availabilityZones: string[]? - - @description('Optional. The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive).') - count: int? - - @description('Optional. The source resource ID to create the agent pool from.') - sourceResourceId: string? - - @description('Optional. Whether to enable auto-scaling for the agent pool.') - enableAutoScaling: bool? - - @description('Optional. Whether to enable encryption at host for the agent pool.') - enableEncryptionAtHost: bool? - - @description('Optional. Whether to enable FIPS for the agent pool.') - enableFIPS: bool? - - @description('Optional. Whether to enable node public IP for the agent pool.') - enableNodePublicIP: bool? - - @description('Optional. Whether to enable Ultra SSD for the agent pool.') - enableUltraSSD: bool? - - @description('Optional. The GPU instance profile of the agent pool.') - gpuInstanceProfile: ('MIG1g' | 'MIG2g' | 'MIG3g' | 'MIG4g' | 'MIG7g')? - - @description('Optional. The kubelet disk type of the agent pool.') - kubeletDiskType: string? - - @description('Optional. The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive).') - maxCount: int? - - @description('Optional. The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive).') - minCount: int? - - @description('Optional. The maximum number of pods that can run on a node.') - maxPods: int? - - @description('Optional. The minimum number of pods that can run on a node.') - minPods: int? - - @description('Optional. The mode of the agent pool.') - mode: ('System' | 'User')? - - @description('Optional. The node labels of the agent pool.') - nodeLabels: object? - - @description('Optional. The node public IP prefix ID of the agent pool.') - nodePublicIpPrefixId: string? - - @description('Optional. The node taints of the agent pool.') - nodeTaints: string[]? - - @description('Optional. The Kubernetes version of the agent pool.') - orchestratorVersion: string? - - @description('Optional. The OS disk size in GB of the agent pool.') - osDiskSizeGB: int? - - @description('Optional. The OS disk type of the agent pool.') - osDiskType: string? - - @description('Optional. The OS SKU of the agent pool.') - osSku: string? - - @description('Optional. The OS type of the agent pool.') - osType: ('Linux' | 'Windows')? - - @description('Optional. The pod subnet ID of the agent pool.') - podSubnetId: string? - - @description('Optional. The proximity placement group resource ID of the agent pool.') - proximityPlacementGroupResourceId: string? - - @description('Optional. The scale down mode of the agent pool.') - scaleDownMode: ('Delete' | 'Deallocate')? - - @description('Optional. The scale set eviction policy of the agent pool.') - scaleSetEvictionPolicy: ('Delete' | 'Deallocate')? - - @description('Optional. The scale set priority of the agent pool.') - scaleSetPriority: ('Low' | 'Regular' | 'Spot')? - - @description('Optional. The spot max price of the agent pool.') - spotMaxPrice: int? - - @description('Optional. The tags of the agent pool.') - tags: object? - - @description('Optional. The type of the agent pool.') - type: ('AvailabilitySet' | 'VirtualMachineScaleSets')? - - @description('Optional. The maximum number of nodes that can be created during an upgrade.') - maxSurge: string? - - @description('Optional. The VM size of the agent pool.') - vmSize: string? - - @description('Optional. The VNet subnet ID of the agent pool.') - vnetSubnetID: string? - - @description('Optional. The workload runtime of the agent pool.') - workloadRuntime: string? - - @description('Optional. The enable default telemetry of the agent pool.') - enableDefaultTelemetry: bool? -}[]? - type scopeMapsType = { @description('Optional. The name of the scope map.') name: string? diff --git a/avm/ptn/azd/aks/main.json b/avm/ptn/azd/aks/main.json index 6986a11e17..4b3cf60a73 100644 --- a/avm/ptn/azd/aks/main.json +++ b/avm/ptn/azd/aks/main.json @@ -6,318 +6,13 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "5631747890720204830" + "templateHash": "10995240226253882039" }, "name": "Azd AKS", "description": "Creates an Azure Kubernetes Service (AKS) cluster with a system agent pool as well as an additional user agent pool.\n\n**Note:** This module is not intended for broad, generic use, as it was designed to cater for the requirements of the AZD CLI product. Feature requests and bug fix requests are welcome if they support the development of the AZD CLI but may not be incorporated if they aim to make this module more generic than what it needs to be for its primary use case.", "owner": "Azure/module-maintainers" }, "definitions": { - "agentPoolType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the agent pool." - } - }, - "availabilityZones": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The availability zones of the agent pool." - } - }, - "count": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." - } - }, - "sourceResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The source resource ID to create the agent pool from." - } - }, - "enableAutoScaling": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable auto-scaling for the agent pool." - } - }, - "enableEncryptionAtHost": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable encryption at host for the agent pool." - } - }, - "enableFIPS": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable FIPS for the agent pool." - } - }, - "enableNodePublicIP": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable node public IP for the agent pool." - } - }, - "enableUltraSSD": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable Ultra SSD for the agent pool." - } - }, - "gpuInstanceProfile": { - "type": "string", - "allowedValues": [ - "MIG1g", - "MIG2g", - "MIG3g", - "MIG4g", - "MIG7g" - ], - "nullable": true, - "metadata": { - "description": "Optional. The GPU instance profile of the agent pool." - } - }, - "kubeletDiskType": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The kubelet disk type of the agent pool." - } - }, - "maxCount": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." - } - }, - "minCount": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." - } - }, - "maxPods": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The maximum number of pods that can run on a node." - } - }, - "minPods": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The minimum number of pods that can run on a node." - } - }, - "mode": { - "type": "string", - "allowedValues": [ - "System", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The mode of the agent pool." - } - }, - "nodeLabels": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. The node labels of the agent pool." - } - }, - "nodePublicIpPrefixId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The node public IP prefix ID of the agent pool." - } - }, - "nodeTaints": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The node taints of the agent pool." - } - }, - "orchestratorVersion": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Kubernetes version of the agent pool." - } - }, - "osDiskSizeGB": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The OS disk size in GB of the agent pool." - } - }, - "osDiskType": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The OS disk type of the agent pool." - } - }, - "osSku": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The OS SKU of the agent pool." - } - }, - "osType": { - "type": "string", - "allowedValues": [ - "Linux", - "Windows" - ], - "nullable": true, - "metadata": { - "description": "Optional. The OS type of the agent pool." - } - }, - "podSubnetId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The pod subnet ID of the agent pool." - } - }, - "proximityPlacementGroupResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The proximity placement group resource ID of the agent pool." - } - }, - "scaleDownMode": { - "type": "string", - "allowedValues": [ - "Deallocate", - "Delete" - ], - "nullable": true, - "metadata": { - "description": "Optional. The scale down mode of the agent pool." - } - }, - "scaleSetEvictionPolicy": { - "type": "string", - "allowedValues": [ - "Deallocate", - "Delete" - ], - "nullable": true, - "metadata": { - "description": "Optional. The scale set eviction policy of the agent pool." - } - }, - "scaleSetPriority": { - "type": "string", - "allowedValues": [ - "Low", - "Regular", - "Spot" - ], - "nullable": true, - "metadata": { - "description": "Optional. The scale set priority of the agent pool." - } - }, - "spotMaxPrice": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The spot max price of the agent pool." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. The tags of the agent pool." - } - }, - "type": { - "type": "string", - "allowedValues": [ - "AvailabilitySet", - "VirtualMachineScaleSets" - ], - "nullable": true, - "metadata": { - "description": "Optional. The type of the agent pool." - } - }, - "maxSurge": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The maximum number of nodes that can be created during an upgrade." - } - }, - "vmSize": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The VM size of the agent pool." - } - }, - "vnetSubnetID": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The VNet subnet ID of the agent pool." - } - }, - "workloadRuntime": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The workload runtime of the agent pool." - } - }, - "enableDefaultTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. The enable default telemetry of the agent pool." - } - } - } - }, - "nullable": true - }, "scopeMapsType": { "type": "array", "items": { @@ -349,72 +44,372 @@ } }, "nullable": true - } - }, - "parameters": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the parent managed cluster. Required if the template is used in a standalone deployment." - } - }, - "containerRegistryName": { - "type": "string", - "minLength": 5, - "maxLength": 50, - "metadata": { - "description": "Required. Name of your Azure Container Registry." - } - }, - "logAnalyticsName": { - "type": "string", - "metadata": { - "description": "Required. The name of the connected log analytics workspace." - } - }, - "keyVaultName": { - "type": "string", - "maxLength": 24, - "metadata": { - "description": "Required. Name of the Key Vault. Must be globally unique." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Specifies the location of AKS cluster. It picks up Resource Group's location by default." - } }, - "tags": { + "agentPoolType": { "type": "object", - "defaultValue": {}, - "metadata": { - "description": "Optional. Custom tags to apply to the AKS resources." - } - }, - "networkPlugin": { - "type": "string", - "defaultValue": "azure", - "allowedValues": [ - "azure", - "kubenet" - ], - "metadata": { - "description": "Optional. Network plugin used for building the Kubernetes network." - } - }, - "networkPolicy": { - "type": "string", - "defaultValue": "azure", - "allowedValues": [ - "azure", - "calico" - ], - "metadata": { - "description": "Optional. Specifies the network policy used for building Kubernetes network. - calico or azure." - } - }, + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the agent pool." + } + }, + "availabilityZones": { + "type": "array", + "items": { + "type": "int" + }, + "nullable": true, + "metadata": { + "description": "Optional. The availability zones of the agent pool." + } + }, + "count": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." + } + }, + "sourceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The source resource ID to create the agent pool from." + } + }, + "enableAutoScaling": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable auto-scaling for the agent pool." + } + }, + "enableEncryptionAtHost": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable encryption at host for the agent pool." + } + }, + "enableFIPS": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable FIPS for the agent pool." + } + }, + "enableNodePublicIP": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable node public IP for the agent pool." + } + }, + "enableUltraSSD": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable Ultra SSD for the agent pool." + } + }, + "gpuInstanceProfile": { + "type": "string", + "allowedValues": [ + "MIG1g", + "MIG2g", + "MIG3g", + "MIG4g", + "MIG7g" + ], + "nullable": true, + "metadata": { + "description": "Optional. The GPU instance profile of the agent pool." + } + }, + "kubeletDiskType": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The kubelet disk type of the agent pool." + } + }, + "maxCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." + } + }, + "minCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." + } + }, + "maxPods": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The maximum number of pods that can run on a node." + } + }, + "minPods": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The minimum number of pods that can run on a node." + } + }, + "mode": { + "type": "string", + "allowedValues": [ + "System", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The mode of the agent pool." + } + }, + "nodeLabels": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The node labels of the agent pool." + } + }, + "nodePublicIpPrefixResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The node public IP prefix ID of the agent pool." + } + }, + "nodeTaints": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The node taints of the agent pool." + } + }, + "orchestratorVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Kubernetes version of the agent pool." + } + }, + "osDiskSizeGB": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The OS disk size in GB of the agent pool." + } + }, + "osDiskType": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The OS disk type of the agent pool." + } + }, + "osSku": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The OS SKU of the agent pool." + } + }, + "osType": { + "type": "string", + "allowedValues": [ + "Linux", + "Windows" + ], + "nullable": true, + "metadata": { + "description": "Optional. The OS type of the agent pool." + } + }, + "podSubnetResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The pod subnet ID of the agent pool." + } + }, + "proximityPlacementGroupResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The proximity placement group resource ID of the agent pool." + } + }, + "scaleDownMode": { + "type": "string", + "allowedValues": [ + "Deallocate", + "Delete" + ], + "nullable": true, + "metadata": { + "description": "Optional. The scale down mode of the agent pool." + } + }, + "scaleSetEvictionPolicy": { + "type": "string", + "allowedValues": [ + "Deallocate", + "Delete" + ], + "nullable": true, + "metadata": { + "description": "Optional. The scale set eviction policy of the agent pool." + } + }, + "scaleSetPriority": { + "type": "string", + "allowedValues": [ + "Low", + "Regular", + "Spot" + ], + "nullable": true, + "metadata": { + "description": "Optional. The scale set priority of the agent pool." + } + }, + "spotMaxPrice": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The spot max price of the agent pool." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The tags of the agent pool." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "AvailabilitySet", + "VirtualMachineScaleSets" + ], + "nullable": true, + "metadata": { + "description": "Optional. The type of the agent pool." + } + }, + "maxSurge": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The maximum number of nodes that can be created during an upgrade." + } + }, + "vmSize": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The VM size of the agent pool." + } + }, + "vnetSubnetResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The VNet subnet ID of the agent pool." + } + }, + "workloadRuntime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The workload runtime of the agent pool." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The enable default telemetry of the agent pool." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/res/container-service/managed-cluster:0.4.1" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the parent managed cluster. Required if the template is used in a standalone deployment." + } + }, + "containerRegistryName": { + "type": "string", + "minLength": 5, + "maxLength": 50, + "metadata": { + "description": "Required. Name of your Azure Container Registry." + } + }, + "keyVaultName": { + "type": "string", + "maxLength": 24, + "metadata": { + "description": "Required. Name of the Key Vault. Must be globally unique." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Specifies the location of AKS cluster. It picks up Resource Group's location by default." + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Custom tags to apply to the AKS resources." + } + }, + "networkPlugin": { + "type": "string", + "defaultValue": "azure", + "allowedValues": [ + "azure", + "kubenet" + ], + "metadata": { + "description": "Optional. Network plugin used for building the Kubernetes network." + } + }, + "networkPolicy": { + "type": "string", + "defaultValue": "azure", + "allowedValues": [ + "azure", + "calico" + ], + "metadata": { + "description": "Optional. Specifies the network policy used for building Kubernetes network. - calico or azure." + } + }, "dnsPrefix": { "type": "string", "defaultValue": "[parameters('name')]", @@ -524,13 +519,6 @@ "description": "Optional. Specifies the SSH RSA public key string for the Linux nodes." } }, - "aadProfileEnableAzureRBAC": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Specifies whether to enable Azure RBAC for Kubernetes authorization." - } - }, "appGatewayResourceId": { "type": "string", "nullable": true, @@ -540,15 +528,8 @@ }, "monitoringWorkspaceResourceId": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. Resource ID of the monitoring log analytics workspace." - } - }, - "agentPools": { - "$ref": "#/definitions/agentPoolType", - "metadata": { - "description": "Optional. Define one or more secondary/additional agent pools." + "description": "Required. Resource ID of the monitoring log analytics workspace." } }, "publicNetworkAccess": { @@ -562,6 +543,17 @@ "description": "Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and networkRuleSetIpRules are not set. Note, requires the 'acrSku' to be 'Premium'." } }, + "loadBalancerSku": { + "type": "string", + "defaultValue": "standard", + "allowedValues": [ + "basic", + "standard" + ], + "metadata": { + "description": "Optional. Specifies the sku of the load balancer used by the virtual machine scale sets used by nodepools." + } + }, "scopeMaps": { "$ref": "#/definitions/scopeMapsType", "metadata": { @@ -570,7 +562,7 @@ }, "webApplicationRoutingEnabled": { "type": "bool", - "nullable": true, + "defaultValue": true, "metadata": { "description": "Optional. Specifies whether the webApplicationRoutingEnabled add-on is enabled or not." } @@ -600,77 +592,193 @@ "metadata": { "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } - } - }, - "variables": { - "aksClusterAdminRole": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b')]", - "acrPullRole": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", - "nodePoolPresets": { - "vmSize": "Standard_DS2_v2", - "count": 3, - "minCount": 3, - "maxCount": 5, - "enableAutoScaling": true, - "availabilityZones": [ - "1", - "2", - "3" - ] }, - "nodePoolBase": { - "osType": "Linux", - "maxPods": 30, - "type": "VirtualMachineScaleSets", - "upgradeSettings": { - "maxSurge": "33%" + "systemPoolConfig": { + "type": "array", + "items": { + "$ref": "#/definitions/agentPoolType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom configuration of system node pool." } }, - "primaryAgentPoolProfile": [ - "[union(createObject('name', 'npsystem', 'mode', 'System'), variables('nodePoolBase'), variables('nodePoolPresets'))]" - ] - }, - "resources": { - "avmTelemetry": { - "condition": "[parameters('enableTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.ptn.azd-aks.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [], - "outputs": { - "telemetry": { - "type": "String", - "value": "For more information, see https://aka.ms/avm/TelemetryInfo" - } - } - } + "agentPoolConfig": { + "type": "array", + "items": { + "$ref": "#/definitions/agentPoolType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom configuration of user node pool." } }, - "logAnalytics": { - "condition": "[not(empty(parameters('logAnalyticsName')))]", - "existing": true, - "type": "Microsoft.OperationalInsights/workspaces", - "apiVersion": "2021-12-01-preview", - "name": "[parameters('logAnalyticsName')]" + "enableKeyvaultSecretsProvider": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Specifies whether the KeyvaultSecretsProvider add-on is enabled or not." + } }, - "managedCluster": { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-managed-cluster', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[parameters('name')]" - }, - "location": { + "disableLocalAccounts": { + "type": "bool", + "defaultValue": true, + "metadata": { + "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." + } + }, + "autoNodeOsUpgradeProfileUpgradeChannel": { + "type": "string", + "defaultValue": "NodeImage", + "allowedValues": [ + "NodeImage", + "None", + "SecurityPatch", + "Unmanaged" + ], + "metadata": { + "description": "Optional. Auto-upgrade channel on the Node Os." + } + }, + "systemPoolSize": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "CostOptimised", + "Standard", + "HighSpec", + "Custom" + ], + "metadata": { + "description": "Optional. The System Pool Preset sizing." + } + }, + "agentPoolSize": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "CostOptimised", + "Standard", + "HighSpec", + "Custom" + ], + "metadata": { + "description": "Optional. The User Pool Preset sizing." + } + }, + "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. 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. Note that management actions are always authorized with RBAC." + } + }, + "enablePurgeProtection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Provide 'true' to enable Key Vault's purge protection feature." + } + }, + "enableVaultForDeployment": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies if the vault is enabled for deployment by script or compute." + } + }, + "enableVaultForTemplateDeployment": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies if the vault is enabled for a template deployment." + } + } + }, + "variables": { + "systemPoolsConfig": "[if(not(empty(parameters('systemPoolConfig'))), parameters('systemPoolConfig'), createArray(union(createObject('name', 'npsystem', 'mode', 'System'), variables('nodePoolBase'), variables('nodePoolPresets')[parameters('systemPoolSize')])))]", + "agentPoolsConfig": "[if(not(empty(parameters('agentPoolConfig'))), parameters('agentPoolConfig'), if(empty(parameters('agentPoolSize')), null(), createArray(union(createObject('name', 'npuser', 'mode', 'User'), variables('nodePoolBase'), variables('nodePoolPresets')[parameters('agentPoolSize')]))))]", + "aksClusterAdminRole": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b')]", + "acrPullRole": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "nodePoolPresets": { + "CostOptimised": { + "vmSize": "Standard_B4ms", + "count": 1, + "minCount": 1, + "maxCount": 3, + "enableAutoScaling": true, + "availabilityZones": [] + }, + "Standard": { + "vmSize": "Standard_DS2_v2", + "count": 3, + "minCount": 3, + "maxCount": 5, + "enableAutoScaling": true, + "availabilityZones": [ + 1, + 2, + 3 + ] + }, + "HighSpec": { + "vmSize": "Standard_D4s_v3", + "count": 3, + "minCount": 3, + "maxCount": 5, + "enableAutoScaling": true, + "availabilityZones": [ + "1", + "2", + "3" + ] + } + }, + "nodePoolBase": { + "osType": "Linux", + "maxPods": 30, + "type": "VirtualMachineScaleSets", + "upgradeSettings": { + "maxSurge": "33%" + } + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.ptn.azd-aks.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "managedCluster": { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-managed-cluster', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('name')]" + }, + "location": { "value": "[parameters('location')]" }, "tags": { @@ -706,18 +814,33 @@ "sshPublicKey": { "value": "[parameters('sshPublicKey')]" }, - "aadProfileEnableAzureRBAC": { - "value": "[parameters('aadProfileEnableAzureRBAC')]" - }, "skuTier": { "value": "[parameters('skuTier')]" }, "appGatewayResourceId": { "value": "[parameters('appGatewayResourceId')]" }, - "monitoringWorkspaceId": { + "monitoringWorkspaceResourceId": { "value": "[parameters('monitoringWorkspaceResourceId')]" }, + "publicNetworkAccess": { + "value": "[parameters('publicNetworkAccess')]" + }, + "autoNodeOsUpgradeProfileUpgradeChannel": { + "value": "[parameters('autoNodeOsUpgradeProfileUpgradeChannel')]" + }, + "enableKeyvaultSecretsProvider": { + "value": "[parameters('enableKeyvaultSecretsProvider')]" + }, + "webApplicationRoutingEnabled": { + "value": "[parameters('webApplicationRoutingEnabled')]" + }, + "disableLocalAccounts": { + "value": "[parameters('disableLocalAccounts')]" + }, + "loadBalancerSku": { + "value": "[parameters('loadBalancerSku')]" + }, "managedIdentities": { "value": { "systemAssigned": true @@ -744,7 +867,7 @@ "enabled": true } ], - "workspaceResourceId": "[if(not(empty(parameters('logAnalyticsName'))), resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsName')), '')]", + "workspaceResourceId": "[parameters('monitoringWorkspaceResourceId')]", "metricCategories": [ { "category": "AllMetrics", @@ -754,17 +877,14 @@ } ] }, - "webApplicationRoutingEnabled": { - "value": "[parameters('webApplicationRoutingEnabled')]" - }, - "primaryAgentPoolProfile": { - "value": "[variables('primaryAgentPoolProfile')]" + "primaryAgentPoolProfiles": { + "value": "[variables('systemPoolsConfig')]" }, "dnsPrefix": { "value": "[parameters('dnsPrefix')]" }, "agentPools": { - "value": "[parameters('agentPools')]" + "value": "[variables('agentPoolsConfig')]" }, "enableTelemetry": { "value": "[parameters('enableTelemetry')]" @@ -787,8 +907,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17708769259435874319" + "version": "0.30.23.60470", + "templateHash": "9290728353306822069" }, "name": "Azure Kubernetes Service (AKS) Managed Clusters", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster.", @@ -796,310 +916,308 @@ }, "definitions": { "agentPoolType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. The name of the agent pool." - } - }, - "availabilityZones": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The availability zones of the agent pool." - } - }, - "count": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." - } - }, - "sourceResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The source resource ID to create the agent pool from." - } - }, - "enableAutoScaling": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable auto-scaling for the agent pool." - } - }, - "enableEncryptionAtHost": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable encryption at host for the agent pool." - } - }, - "enableFIPS": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable FIPS for the agent pool." - } - }, - "enableNodePublicIP": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable node public IP for the agent pool." - } - }, - "enableUltraSSD": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to enable Ultra SSD for the agent pool." - } - }, - "gpuInstanceProfile": { - "type": "string", - "allowedValues": [ - "MIG1g", - "MIG2g", - "MIG3g", - "MIG4g", - "MIG7g" - ], - "nullable": true, - "metadata": { - "description": "Optional. The GPU instance profile of the agent pool." - } - }, - "kubeletDiskType": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The kubelet disk type of the agent pool." - } - }, - "maxCount": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." - } - }, - "minCount": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." - } - }, - "maxPods": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The maximum number of pods that can run on a node." - } - }, - "minPods": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The minimum number of pods that can run on a node." - } - }, - "mode": { - "type": "string", - "allowedValues": [ - "System", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The mode of the agent pool." - } - }, - "nodeLabels": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. The node labels of the agent pool." - } - }, - "nodePublicIpPrefixId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The node public IP prefix ID of the agent pool." - } - }, - "nodeTaints": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The node taints of the agent pool." - } - }, - "orchestratorVersion": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Kubernetes version of the agent pool." - } - }, - "osDiskSizeGB": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The OS disk size in GB of the agent pool." - } - }, - "osDiskType": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The OS disk type of the agent pool." - } - }, - "osSku": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The OS SKU of the agent pool." - } - }, - "osType": { - "type": "string", - "allowedValues": [ - "Linux", - "Windows" - ], - "nullable": true, - "metadata": { - "description": "Optional. The OS type of the agent pool." - } - }, - "podSubnetId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The pod subnet ID of the agent pool." - } - }, - "proximityPlacementGroupResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The proximity placement group resource ID of the agent pool." - } - }, - "scaleDownMode": { - "type": "string", - "allowedValues": [ - "Deallocate", - "Delete" - ], - "nullable": true, - "metadata": { - "description": "Optional. The scale down mode of the agent pool." - } - }, - "scaleSetEvictionPolicy": { - "type": "string", - "allowedValues": [ - "Deallocate", - "Delete" - ], - "nullable": true, - "metadata": { - "description": "Optional. The scale set eviction policy of the agent pool." - } - }, - "scaleSetPriority": { - "type": "string", - "allowedValues": [ - "Low", - "Regular", - "Spot" - ], - "nullable": true, - "metadata": { - "description": "Optional. The scale set priority of the agent pool." - } - }, - "spotMaxPrice": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The spot max price of the agent pool." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. The tags of the agent pool." - } - }, - "type": { - "type": "string", - "allowedValues": [ - "AvailabilitySet", - "VirtualMachineScaleSets" - ], - "nullable": true, - "metadata": { - "description": "Optional. The type of the agent pool." - } - }, - "maxSurge": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The maximum number of nodes that can be created during an upgrade." - } - }, - "vmSize": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The VM size of the agent pool." - } - }, - "vnetSubnetID": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The VNet subnet ID of the agent pool." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the agent pool." + } + }, + "availabilityZones": { + "type": "array", + "items": { + "type": "int" }, - "workloadRuntime": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The workload runtime of the agent pool." - } + "nullable": true, + "metadata": { + "description": "Optional. The availability zones of the agent pool." + } + }, + "count": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." + } + }, + "sourceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The source resource ID to create the agent pool from." + } + }, + "enableAutoScaling": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable auto-scaling for the agent pool." + } + }, + "enableEncryptionAtHost": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable encryption at host for the agent pool." + } + }, + "enableFIPS": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable FIPS for the agent pool." + } + }, + "enableNodePublicIP": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable node public IP for the agent pool." + } + }, + "enableUltraSSD": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable Ultra SSD for the agent pool." + } + }, + "gpuInstanceProfile": { + "type": "string", + "allowedValues": [ + "MIG1g", + "MIG2g", + "MIG3g", + "MIG4g", + "MIG7g" + ], + "nullable": true, + "metadata": { + "description": "Optional. The GPU instance profile of the agent pool." + } + }, + "kubeletDiskType": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The kubelet disk type of the agent pool." + } + }, + "maxCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The maximum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." + } + }, + "minCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The minimum number of agents (VMs) to host docker containers. Allowed values must be in the range of 1 to 100 (inclusive)." + } + }, + "maxPods": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The maximum number of pods that can run on a node." + } + }, + "minPods": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The minimum number of pods that can run on a node." + } + }, + "mode": { + "type": "string", + "allowedValues": [ + "System", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The mode of the agent pool." + } + }, + "nodeLabels": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The node labels of the agent pool." + } + }, + "nodePublicIpPrefixResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The node public IP prefix ID of the agent pool." + } + }, + "nodeTaints": { + "type": "array", + "items": { + "type": "string" }, - "enableDefaultTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. The enable default telemetry of the agent pool." - } + "nullable": true, + "metadata": { + "description": "Optional. The node taints of the agent pool." + } + }, + "orchestratorVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Kubernetes version of the agent pool." + } + }, + "osDiskSizeGB": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The OS disk size in GB of the agent pool." + } + }, + "osDiskType": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The OS disk type of the agent pool." + } + }, + "osSku": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The OS SKU of the agent pool." + } + }, + "osType": { + "type": "string", + "allowedValues": [ + "Linux", + "Windows" + ], + "nullable": true, + "metadata": { + "description": "Optional. The OS type of the agent pool." + } + }, + "podSubnetResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The pod subnet ID of the agent pool." + } + }, + "proximityPlacementGroupResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The proximity placement group resource ID of the agent pool." + } + }, + "scaleDownMode": { + "type": "string", + "allowedValues": [ + "Deallocate", + "Delete" + ], + "nullable": true, + "metadata": { + "description": "Optional. The scale down mode of the agent pool." + } + }, + "scaleSetEvictionPolicy": { + "type": "string", + "allowedValues": [ + "Deallocate", + "Delete" + ], + "nullable": true, + "metadata": { + "description": "Optional. The scale set eviction policy of the agent pool." + } + }, + "scaleSetPriority": { + "type": "string", + "allowedValues": [ + "Low", + "Regular", + "Spot" + ], + "nullable": true, + "metadata": { + "description": "Optional. The scale set priority of the agent pool." + } + }, + "spotMaxPrice": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The spot max price of the agent pool." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The tags of the agent pool." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "AvailabilitySet", + "VirtualMachineScaleSets" + ], + "nullable": true, + "metadata": { + "description": "Optional. The type of the agent pool." + } + }, + "maxSurge": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The maximum number of nodes that can be created during an upgrade." + } + }, + "vmSize": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The VM size of the agent pool." + } + }, + "vnetSubnetResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The VNet subnet ID of the agent pool." + } + }, + "workloadRuntime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The workload runtime of the agent pool." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The enable default telemetry of the agent pool." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "managedIdentitiesType": { "type": "object", @@ -1122,7 +1240,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "lockType": { "type": "object", @@ -1147,7 +1267,10 @@ } } }, - "nullable": true + "nullable": true, + "metadata": { + "__bicep_export!": true + } }, "roleAssignmentType": { "type": "array", @@ -1220,7 +1343,10 @@ } } }, - "nullable": true + "nullable": true, + "metadata": { + "__bicep_export!": true + } }, "diagnosticSettingType": { "type": "array", @@ -1340,7 +1466,10 @@ } } }, - "nullable": true + "nullable": true, + "metadata": { + "__bicep_export!": true + } }, "fluxConfigurationProtectedSettingsType": { "type": "object", @@ -1353,7 +1482,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "extensionType": { "type": "object", @@ -1415,7 +1546,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "customerManagedKeyType": { "type": "object", @@ -1450,11 +1583,23 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "maintenanceConfigurationType": { "type": "object", "properties": { + "name": { + "type": "string", + "allowedValues": [ + "aksManagedAutoUpgradeSchedule", + "aksManagedNodeOSUpgradeSchedule" + ], + "metadata": { + "description": "Required. Name of maintenance window." + } + }, "maintenanceWindow": { "type": "object", "metadata": { @@ -1462,7 +1607,9 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } } }, "parameters": { @@ -1488,6 +1635,7 @@ }, "managedIdentities": { "$ref": "#/definitions/managedIdentitiesType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." } @@ -1668,6 +1816,9 @@ }, "aadProfileAdminGroupObjectIDs": { "type": "array", + "items": { + "type": "string" + }, "nullable": true, "metadata": { "description": "Optional. Specifies the AAD group object IDs that will have admin role of the cluster." @@ -1696,7 +1847,7 @@ }, "disableLocalAccounts": { "type": "bool", - "defaultValue": false, + "defaultValue": true, "metadata": { "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." } @@ -1710,6 +1861,9 @@ }, "authorizedIPRanges": { "type": "array", + "items": { + "type": "string" + }, "nullable": true, "metadata": { "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." @@ -1755,20 +1909,31 @@ "description": "Optional. Private DNS Zone configuration. Set to 'system' and AKS will create a private DNS zone in the node resource group. Set to '' to disable private DNS Zone creation and use public DNS. Supply the resource ID here of an existing Private DNS zone to use an existing zone." } }, - "primaryAgentPoolProfile": { + "primaryAgentPoolProfiles": { "type": "array", + "items": { + "$ref": "#/definitions/agentPoolType" + }, "metadata": { "description": "Required. Properties of the primary agent pool." } }, "agentPools": { - "$ref": "#/definitions/agentPoolType", + "type": "array", + "items": { + "$ref": "#/definitions/agentPoolType" + }, + "nullable": true, "metadata": { "description": "Optional. Define one or more secondary/additional agent pools." } }, - "maintenanceConfiguration": { - "$ref": "#/definitions/maintenanceConfigurationType", + "maintenanceConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/maintenanceConfigurationType" + }, + "nullable": true, "metadata": { "description": "Optional. Whether or not to use AKS Automatic mode." } @@ -1921,8 +2086,8 @@ } }, "autoScalerProfileMaxGracefulTerminationSec": { - "type": "string", - "defaultValue": "600", + "type": "int", + "defaultValue": 600, "metadata": { "description": "Optional. Specifies the max graceful termination time interval in seconds for the auto-scaler of the AKS cluster." } @@ -1948,8 +2113,8 @@ } }, "autoScalerProfileMaxEmptyBulkDelete": { - "type": "string", - "defaultValue": "10", + "type": "int", + "defaultValue": 10, "metadata": { "description": "Optional. Specifies the maximum empty bulk delete for the auto-scaler of the AKS cluster." } @@ -1962,8 +2127,8 @@ } }, "autoScalerProfileMaxTotalUnreadyPercentage": { - "type": "string", - "defaultValue": "45", + "type": "int", + "defaultValue": 45, "metadata": { "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." } @@ -1976,8 +2141,8 @@ } }, "autoScalerProfileOkTotalUnreadyCount": { - "type": "string", - "defaultValue": "3", + "type": "int", + "defaultValue": 3, "metadata": { "description": "Optional. Specifies the OK total unready count for the auto-scaler of the AKS cluster." } @@ -2010,6 +2175,19 @@ "description": "Optional. Auto-upgrade channel on the AKS cluster." } }, + "autoNodeOsUpgradeProfileUpgradeChannel": { + "type": "string", + "defaultValue": "Unmanaged", + "allowedValues": [ + "NodeImage", + "None", + "SecurityPatch", + "Unmanaged" + ], + "metadata": { + "description": "Optional. Auto-upgrade channel on the Node Os." + } + }, "podIdentityProfileAllowNetworkPluginKubenet": { "type": "bool", "defaultValue": false, @@ -2133,7 +2311,7 @@ "description": "Optional. Specifies whether the OMS agent is enabled." } }, - "monitoringWorkspaceId": { + "monitoringWorkspaceResourceId": { "type": "string", "nullable": true, "metadata": { @@ -2175,6 +2353,7 @@ }, "fluxExtension": { "$ref": "#/definitions/extensionType", + "nullable": true, "metadata": { "description": "Optional. Settings and configurations for the flux extension." } @@ -2200,8 +2379,16 @@ "description": "Optional. Enables Kubernetes Event-driven Autoscaling (KEDA)." } }, + "vpaAddon": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Whether to enable VPA add-on in cluster. Default value is false." + } + }, "customerManagedKey": { "$ref": "#/definitions/customerManagedKeyType", + "nullable": true, "metadata": { "description": "Optional. The customer managed key definition." } @@ -2305,7 +2492,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.containerservice-managedcluster.{0}.{1}', replace('0.3.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.containerservice-managedcluster.{0}.{1}', replace('0.4.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -2342,12 +2529,12 @@ "tier": "[parameters('skuTier')]" }, "properties": { + "agentPoolProfiles": "[map(parameters('primaryAgentPoolProfiles'), lambda('profile', createObject('name', lambdaVariables('profile').name, 'count', coalesce(lambdaVariables('profile').count, 1), 'availabilityZones', map(coalesce(tryGet(lambdaVariables('profile'), 'availabilityZones'), createArray(1, 2, 3)), lambda('zone', format('{0}', lambdaVariables('zone')))), 'creationData', if(not(empty(tryGet(lambdaVariables('profile'), 'sourceResourceId'))), createObject('sourceResourceId', lambdaVariables('profile').sourceResourceId), null()), 'enableAutoScaling', coalesce(tryGet(lambdaVariables('profile'), 'enableAutoScaling'), false()), 'enableEncryptionAtHost', coalesce(tryGet(lambdaVariables('profile'), 'enableEncryptionAtHost'), false()), 'enableFIPS', coalesce(tryGet(lambdaVariables('profile'), 'enableFIPS'), false()), 'enableNodePublicIP', coalesce(tryGet(lambdaVariables('profile'), 'enableNodePublicIP'), false()), 'enableUltraSSD', coalesce(tryGet(lambdaVariables('profile'), 'enableUltraSSD'), false()), 'gpuInstanceProfile', tryGet(lambdaVariables('profile'), 'gpuInstanceProfile'), 'kubeletDiskType', tryGet(lambdaVariables('profile'), 'kubeletDiskType'), 'maxCount', tryGet(lambdaVariables('profile'), 'maxCount'), 'maxPods', tryGet(lambdaVariables('profile'), 'maxPods'), 'minCount', tryGet(lambdaVariables('profile'), 'minCount'), 'mode', tryGet(lambdaVariables('profile'), 'mode'), 'nodeLabels', tryGet(lambdaVariables('profile'), 'nodeLabels'), 'nodePublicIPPrefixID', tryGet(lambdaVariables('profile'), 'nodePublicIpPrefixResourceId'), 'nodeTaints', tryGet(lambdaVariables('profile'), 'nodeTaints'), 'orchestratorVersion', tryGet(lambdaVariables('profile'), 'orchestratorVersion'), 'osDiskSizeGB', tryGet(lambdaVariables('profile'), 'osDiskSizeGB'), 'osDiskType', tryGet(lambdaVariables('profile'), 'osDiskType'), 'osType', coalesce(tryGet(lambdaVariables('profile'), 'osType'), 'Linux'), 'podSubnetID', tryGet(lambdaVariables('profile'), 'podSubnetResourceId'), 'proximityPlacementGroupID', tryGet(lambdaVariables('profile'), 'proximityPlacementGroupResourceId'), 'scaleDownMode', coalesce(tryGet(lambdaVariables('profile'), 'scaleDownMode'), 'Delete'), 'scaleSetEvictionPolicy', coalesce(tryGet(lambdaVariables('profile'), 'scaleSetEvictionPolicy'), 'Delete'), 'scaleSetPriority', tryGet(lambdaVariables('profile'), 'scaleSetPriority'), 'spotMaxPrice', tryGet(lambdaVariables('profile'), 'spotMaxPrice'), 'tags', tryGet(lambdaVariables('profile'), 'tags'), 'type', tryGet(lambdaVariables('profile'), 'type'), 'upgradeSettings', createObject('maxSurge', tryGet(lambdaVariables('profile'), 'maxSurge')), 'vmSize', coalesce(tryGet(lambdaVariables('profile'), 'vmSize'), 'Standard_D2s_v3'), 'vnetSubnetID', tryGet(lambdaVariables('profile'), 'vnetSubnetResourceId'), 'workloadRuntime', tryGet(lambdaVariables('profile'), 'workloadRuntime'))))]", "httpProxyConfig": "[parameters('httpProxyConfig')]", "identityProfile": "[parameters('identityProfile')]", "diskEncryptionSetID": "[parameters('diskEncryptionSetResourceId')]", "kubernetesVersion": "[parameters('kubernetesVersion')]", "dnsPrefix": "[parameters('dnsPrefix')]", - "agentPoolProfiles": "[parameters('primaryAgentPoolProfile')]", "linuxProfile": "[if(not(empty(parameters('sshPublicKey'))), createObject('adminUsername', parameters('adminUsername'), 'ssh', createObject('publicKeys', createArray(createObject('keyData', coalesce(parameters('sshPublicKey'), ''))))), null())]", "servicePrincipalProfile": "[parameters('aksServicePrincipalProfile')]", "metricsProfile": { @@ -2370,8 +2557,8 @@ "config": "[if(and(parameters('ingressApplicationGatewayEnabled'), not(empty(parameters('appGatewayResourceId')))), createObject('applicationGatewayId', parameters('appGatewayResourceId'), 'effectiveApplicationGatewayId', parameters('appGatewayResourceId')), null())]" }, "omsagent": { - "enabled": "[and(parameters('omsAgentEnabled'), not(empty(parameters('monitoringWorkspaceId'))))]", - "config": "[if(and(parameters('omsAgentEnabled'), not(empty(parameters('monitoringWorkspaceId')))), createObject('logAnalyticsWorkspaceResourceID', parameters('monitoringWorkspaceId')), null())]" + "enabled": "[and(parameters('omsAgentEnabled'), not(empty(parameters('monitoringWorkspaceResourceId'))))]", + "config": "[if(and(parameters('omsAgentEnabled'), not(empty(parameters('monitoringWorkspaceResourceId')))), createObject('logAnalyticsWorkspaceResourceID', parameters('monitoringWorkspaceResourceId')), null())]" }, "aciConnectorLinux": { "enabled": "[parameters('aciConnectorLinuxEnabled')]" @@ -2400,6 +2587,9 @@ "workloadAutoScalerProfile": { "keda": { "enabled": "[parameters('kedaAddon')]" + }, + "verticalPodAutoscaler": { + "enabled": "[parameters('vpaAddon')]" } }, "networkProfile": { @@ -2431,12 +2621,12 @@ "autoScalerProfile": { "balance-similar-node-groups": "[toLower(string(parameters('autoScalerProfileBalanceSimilarNodeGroups')))]", "expander": "[parameters('autoScalerProfileExpander')]", - "max-empty-bulk-delete": "[parameters('autoScalerProfileMaxEmptyBulkDelete')]", - "max-graceful-termination-sec": "[parameters('autoScalerProfileMaxGracefulTerminationSec')]", + "max-empty-bulk-delete": "[format('{0}', parameters('autoScalerProfileMaxEmptyBulkDelete'))]", + "max-graceful-termination-sec": "[format('{0}', parameters('autoScalerProfileMaxGracefulTerminationSec'))]", "max-node-provision-time": "[parameters('autoScalerProfileMaxNodeProvisionTime')]", - "max-total-unready-percentage": "[parameters('autoScalerProfileMaxTotalUnreadyPercentage')]", + "max-total-unready-percentage": "[format('{0}', parameters('autoScalerProfileMaxTotalUnreadyPercentage'))]", "new-pod-scale-up-delay": "[parameters('autoScalerProfileNewPodScaleUpDelay')]", - "ok-total-unready-count": "[parameters('autoScalerProfileOkTotalUnreadyCount')]", + "ok-total-unready-count": "[format('{0}', parameters('autoScalerProfileOkTotalUnreadyCount'))]", "scale-down-delay-after-add": "[parameters('autoScalerProfileScaleDownDelayAfterAdd')]", "scale-down-delay-after-delete": "[parameters('autoScalerProfileScaleDownDelayAfterDelete')]", "scale-down-delay-after-failure": "[parameters('autoScalerProfileScaleDownDelayAfterFailure')]", @@ -2448,7 +2638,8 @@ "skip-nodes-with-system-pods": "[toLower(string(parameters('autoScalerProfileSkipNodesWithSystemPods')))]" }, "autoUpgradeProfile": { - "upgradeChannel": "[parameters('autoUpgradeProfileUpgradeChannel')]" + "upgradeChannel": "[parameters('autoUpgradeProfileUpgradeChannel')]", + "nodeOSUpgradeChannel": "[parameters('autoNodeOsUpgradeProfileUpgradeChannel')]" }, "apiServerAccessProfile": { "authorizedIPRanges": "[parameters('authorizedIPRanges')]", @@ -2458,7 +2649,7 @@ "privateDNSZone": "[parameters('privateDNSZone')]" }, "azureMonitorProfile": { - "containerInsights": "[if(parameters('enableContainerInsights'), createObject('enabled', parameters('enableContainerInsights'), 'logAnalyticsWorkspaceResourceId', if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), null()), 'disableCustomMetrics', parameters('disableCustomMetrics'), 'disablePrometheusMetricsScraping', parameters('disablePrometheusMetricsScraping'), 'syslogPort', parameters('syslogPort')), null())]", + "containerInsights": "[if(parameters('enableContainerInsights'), createObject('enabled', parameters('enableContainerInsights'), 'logAnalyticsWorkspaceResourceId', if(not(empty(parameters('monitoringWorkspaceResourceId'))), parameters('monitoringWorkspaceResourceId'), null()), 'disableCustomMetrics', parameters('disableCustomMetrics'), 'disablePrometheusMetricsScraping', parameters('disablePrometheusMetricsScraping'), 'syslogPort', parameters('syslogPort')), null())]", "metrics": "[if(parameters('enableAzureMonitorProfileMetrics'), createObject('enabled', parameters('enableAzureMonitorProfileMetrics'), 'kubeStateMetrics', createObject('metricLabelsAllowlist', parameters('metricLabelsAllowlist'), 'metricAnnotationsAllowList', parameters('metricAnnotationsAllowList'))), null())]" }, "podIdentityProfile": { @@ -2468,7 +2659,7 @@ "userAssignedIdentityExceptions": "[parameters('podIdentityProfileUserAssignedIdentityExceptions')]" }, "securityProfile": { - "defender": "[if(parameters('enableAzureDefender'), createObject('securityMonitoring', createObject('enabled', parameters('enableAzureDefender')), 'logAnalyticsWorkspaceResourceId', parameters('monitoringWorkspaceId')), null())]", + "defender": "[if(parameters('enableAzureDefender'), createObject('securityMonitoring', createObject('enabled', parameters('enableAzureDefender')), 'logAnalyticsWorkspaceResourceId', parameters('monitoringWorkspaceResourceId')), null())]", "workloadIdentity": "[if(parameters('enableWorkloadIdentity'), createObject('enabled', parameters('enableWorkloadIdentity')), null())]", "imageCleaner": "[if(parameters('enableImageCleaner'), createObject('enabled', parameters('enableImageCleaner'), 'intervalHours', parameters('imageCleanerIntervalHours')), null())]" }, @@ -2590,18 +2781,24 @@ ] }, "managedCluster_maintenanceConfigurations": { - "condition": "[not(empty(parameters('maintenanceConfiguration')))]", + "copy": { + "name": "managedCluster_maintenanceConfigurations", + "count": "[length(coalesce(parameters('maintenanceConfigurations'), createArray()))]" + }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-ManagedCluster-MaintenanceConfigurations', uniqueString(deployment().name, parameters('location')))]", + "name": "[format('{0}-ManagedCluster-MaintenanceConfiguration-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { + "name": { + "value": "[coalesce(parameters('maintenanceConfigurations'), createArray())[copyIndex()].name]" + }, "maintenanceWindow": { - "value": "[parameters('maintenanceConfiguration').maintenanceWindow]" + "value": "[coalesce(parameters('maintenanceConfigurations'), createArray())[copyIndex()].maintenanceWindow]" }, "managedClusterName": { "value": "[parameters('name')]" @@ -2613,8 +2810,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12168542117744033419" + "version": "0.30.23.60470", + "templateHash": "2505380725266419010" }, "name": "Azure Kubernetes Service (AKS) Managed Cluster Maintenance Configurations", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster Maintenance Configurations.", @@ -2745,8 +2942,8 @@ "nodeLabels": { "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'nodeLabels')]" }, - "nodePublicIpPrefixId": { - "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'nodePublicIpPrefixId')]" + "nodePublicIpPrefixResourceId": { + "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'nodePublicIpPrefixResourceId')]" }, "nodeTaints": { "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'nodeTaints')]" @@ -2766,8 +2963,8 @@ "osType": { "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'osType')]" }, - "podSubnetId": { - "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'podSubnetId')]" + "podSubnetResourceId": { + "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'podSubnetResourceId')]" }, "proximityPlacementGroupResourceId": { "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'proximityPlacementGroupResourceId')]" @@ -2796,8 +2993,8 @@ "vmSize": { "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'vmSize')]" }, - "vnetSubnetId": { - "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'vnetSubnetId')]" + "vnetSubnetResourceId": { + "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'vnetSubnetResourceId')]" }, "workloadRuntime": { "value": "[tryGet(coalesce(parameters('agentPools'), createArray())[copyIndex()], 'workloadRuntime')]" @@ -2810,8 +3007,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2004205618690542488" + "version": "0.30.23.60470", + "templateHash": "13856766172443517827" }, "name": "Azure Kubernetes Service (AKS) Managed Cluster Agent Pools", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster Agent Pool.", @@ -2832,7 +3029,14 @@ }, "availabilityZones": { "type": "array", - "nullable": true, + "items": { + "type": "int" + }, + "defaultValue": [ + 1, + 2, + 3 + ], "metadata": { "description": "Optional. The list of Availability zones to use for nodes. This can only be specified if the AgentPoolType property is \"VirtualMachineScaleSets\"." } @@ -2944,7 +3148,7 @@ "description": "Optional. The node labels to be persisted across all nodes in agent pool." } }, - "nodePublicIpPrefixId": { + "nodePublicIpPrefixResourceId": { "type": "string", "nullable": true, "metadata": { @@ -3008,11 +3212,11 @@ "description": "Optional. The operating system type. The default is Linux." } }, - "podSubnetId": { + "podSubnetResourceId": { "type": "string", "nullable": true, "metadata": { - "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}." + "description": "Optional. Subnet resource 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}." } }, "proximityPlacementGroupResourceId": { @@ -3090,7 +3294,7 @@ "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." } }, - "vnetSubnetId": { + "vnetSubnetResourceId": { "type": "string", "nullable": true, "metadata": { @@ -3117,7 +3321,7 @@ "apiVersion": "2023-07-02-preview", "name": "[format('{0}/{1}', parameters('managedClusterName'), parameters('name'))]", "properties": { - "availabilityZones": "[parameters('availabilityZones')]", + "availabilityZones": "[map(coalesce(parameters('availabilityZones'), createArray()), lambda('zone', format('{0}', lambdaVariables('zone'))))]", "count": "[parameters('count')]", "creationData": "[if(not(empty(parameters('sourceResourceId'))), createObject('sourceResourceId', parameters('sourceResourceId')), null())]", "enableAutoScaling": "[parameters('enableAutoScaling')]", @@ -3132,14 +3336,14 @@ "minCount": "[parameters('minCount')]", "mode": "[parameters('mode')]", "nodeLabels": "[parameters('nodeLabels')]", - "nodePublicIPPrefixID": "[parameters('nodePublicIpPrefixId')]", + "nodePublicIPPrefixID": "[parameters('nodePublicIpPrefixResourceId')]", "nodeTaints": "[parameters('nodeTaints')]", "orchestratorVersion": "[parameters('orchestratorVersion')]", "osDiskSizeGB": "[parameters('osDiskSizeGB')]", "osDiskType": "[parameters('osDiskType')]", "osSKU": "[parameters('osSku')]", "osType": "[parameters('osType')]", - "podSubnetID": "[parameters('podSubnetId')]", + "podSubnetID": "[parameters('podSubnetResourceId')]", "proximityPlacementGroupID": "[parameters('proximityPlacementGroupResourceId')]", "scaleDownMode": "[parameters('scaleDownMode')]", "scaleSetEvictionPolicy": "[parameters('scaleSetEvictionPolicy')]", @@ -3151,7 +3355,7 @@ "maxSurge": "[parameters('maxSurge')]" }, "vmSize": "[parameters('vmSize')]", - "vnetSubnetID": "[parameters('vnetSubnetId')]", + "vnetSubnetID": "[parameters('vnetSubnetResourceId')]", "workloadRuntime": "[parameters('workloadRuntime')]" }, "dependsOn": [ @@ -3750,10 +3954,7 @@ } } } - }, - "dependsOn": [ - "logAnalytics" - ] + } }, "containerRegistry": { "type": "Microsoft.Resources/deployments", @@ -3799,7 +4000,7 @@ "enabled": true } ], - "workspaceResourceId": "[if(not(empty(parameters('logAnalyticsName'))), resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsName')), '')]", + "workspaceResourceId": "[parameters('monitoringWorkspaceResourceId')]", "metricCategories": [ { "category": "AllMetrics", @@ -6445,7 +6646,6 @@ } }, "dependsOn": [ - "logAnalytics", "managedCluster" ] }, @@ -6465,6 +6665,18 @@ "enableTelemetry": { "value": "[parameters('enableTelemetry')]" }, + "enableRbacAuthorization": { + "value": "[parameters('enableRbacAuthorization')]" + }, + "enableVaultForDeployment": { + "value": "[parameters('enableVaultForDeployment')]" + }, + "enableVaultForTemplateDeployment": { + "value": "[parameters('enableVaultForTemplateDeployment')]" + }, + "enablePurgeProtection": { + "value": "[parameters('enablePurgeProtection')]" + }, "accessPolicies": { "value": [ { diff --git a/avm/ptn/azd/aks/tests/e2e/defaults/dependencies.bicep b/avm/ptn/azd/aks/tests/e2e/defaults/dependencies.bicep index 9961f0c426..e80828420c 100644 --- a/avm/ptn/azd/aks/tests/e2e/defaults/dependencies.bicep +++ b/avm/ptn/azd/aks/tests/e2e/defaults/dependencies.bicep @@ -53,4 +53,4 @@ resource app 'Microsoft.Web/sites@2022-09-01' = { output identityPrincipalId string = app.identity.principalId @description('The resource ID of the created Log Analytics Workspace.') -output logAnalyticsWorkspaceResourceId string = logAnalyticsWorkspace.name +output logAnalyticsResourceId string = logAnalyticsWorkspace.id diff --git a/avm/ptn/azd/aks/tests/e2e/defaults/main.test.bicep b/avm/ptn/azd/aks/tests/e2e/defaults/main.test.bicep index 0d0451cc8d..898e697da5 100644 --- a/avm/ptn/azd/aks/tests/e2e/defaults/main.test.bicep +++ b/avm/ptn/azd/aks/tests/e2e/defaults/main.test.bicep @@ -11,15 +11,16 @@ metadata description = 'This instance deploys the module with the minimum set of @maxLength(90) param resourceGroupName string = 'dep-${namePrefix}-azd-aks-${serviceShort}-rg' -@description('Optional. The location to deploy resources to.') -param resourceLocation string = deployment().location - @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') param serviceShort string = 'paamin' @description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') param namePrefix string = '#_namePrefix_#' +// Enforced location als not all regions have quota available +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + // ============ // // Dependencies // // ============ // @@ -28,14 +29,14 @@ param namePrefix string = '#_namePrefix_#' // ================= resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { name: resourceGroupName - location: resourceLocation + location: enforcedLocation } module nestedDependencies 'dependencies.bicep' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dependencies' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dependencies' scope: resourceGroup params: { - location: resourceLocation + location: enforcedLocation appName: 'dep-${namePrefix}-app-${serviceShort}' appServicePlanName: 'dep-${namePrefix}-apps-${serviceShort}' logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' @@ -50,14 +51,14 @@ module nestedDependencies 'dependencies.bicep' = { module testDeployment '../../../main.bicep' = [ for iteration in ['init', 'idem']: { scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' params: { name: 'mc${uniqueString(deployment().name)}-${serviceShort}' - containerRegistryName: '${uniqueString(deployment().name, resourceLocation)}testcontainerregistry${serviceShort}' - logAnalyticsName: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + containerRegistryName: '${uniqueString(deployment().name, enforcedLocation)}testcontainerregistry${serviceShort}' keyVaultName: 'kv${uniqueString(deployment().name)}-${serviceShort}' - location: resourceLocation + location: enforcedLocation principalId: nestedDependencies.outputs.identityPrincipalId + monitoringWorkspaceResourceId: nestedDependencies.outputs.logAnalyticsResourceId principalType: 'ServicePrincipal' } } diff --git a/avm/ptn/azd/aks/tests/e2e/max/dependencies.bicep b/avm/ptn/azd/aks/tests/e2e/max/dependencies.bicep index 9961f0c426..e80828420c 100644 --- a/avm/ptn/azd/aks/tests/e2e/max/dependencies.bicep +++ b/avm/ptn/azd/aks/tests/e2e/max/dependencies.bicep @@ -53,4 +53,4 @@ resource app 'Microsoft.Web/sites@2022-09-01' = { output identityPrincipalId string = app.identity.principalId @description('The resource ID of the created Log Analytics Workspace.') -output logAnalyticsWorkspaceResourceId string = logAnalyticsWorkspace.name +output logAnalyticsResourceId string = logAnalyticsWorkspace.id diff --git a/avm/ptn/azd/aks/tests/e2e/max/main.test.bicep b/avm/ptn/azd/aks/tests/e2e/max/main.test.bicep index cc61a356d6..baf7bef490 100644 --- a/avm/ptn/azd/aks/tests/e2e/max/main.test.bicep +++ b/avm/ptn/azd/aks/tests/e2e/max/main.test.bicep @@ -63,7 +63,16 @@ module testDeployment '../../../main.bicep' = [ containerRegistryName: '${uniqueString(deployment().name, enforcedLocation)}testcontainerregistry${serviceShort}' skuTier: 'Free' webApplicationRoutingEnabled: true - agentPools: [ + monitoringWorkspaceResourceId: nestedDependencies.outputs.logAnalyticsResourceId + keyVaultName: 'kv${uniqueString(deployment().name)}-${serviceShort}' + location: enforcedLocation + principalId: nestedDependencies.outputs.identityPrincipalId + acrSku: 'Basic' + dnsPrefix: 'dep-${namePrefix}-dns-${serviceShort}' + principalType: 'ServicePrincipal' + containerRegistryRoleName: containerRegistryRoleName + aksClusterRoleAssignmentName: aksClusterRoleAssignmentName + agentPoolConfig: [ { name: 'npuserpool' mode: 'User' @@ -71,18 +80,26 @@ module testDeployment '../../../main.bicep' = [ maxPods: 30 type: 'VirtualMachineScaleSets' maxSurge: '33%' - vmSize: 'standard_a2_v2' + vmSize: 'Standard_DS2_v2' + } + ] + agentPoolSize: 'Standard' + systemPoolConfig: [ + { + name: 'npsystem' + mode: 'System' + vmSize: 'Standard_DS2_v2' + count: 3 + minCount: 3 + maxCount: 5 + enableAutoScaling: true + availabilityZones: [ + 1 + 2 + 3 + ] } ] - logAnalyticsName: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - keyVaultName: 'kv${uniqueString(deployment().name)}-${serviceShort}' - location: enforcedLocation - principalId: nestedDependencies.outputs.identityPrincipalId - acrSku: 'Basic' - dnsPrefix: 'dep-${namePrefix}-dns-${serviceShort}' - principalType: 'ServicePrincipal' - containerRegistryRoleName: containerRegistryRoleName - aksClusterRoleAssignmentName: aksClusterRoleAssignmentName } } ] diff --git a/avm/ptn/azd/apim-api/README.md b/avm/ptn/azd/apim-api/README.md index a063fabfb7..51481ecc85 100644 --- a/avm/ptn/azd/apim-api/README.md +++ b/avm/ptn/azd/apim-api/README.md @@ -19,7 +19,7 @@ Creates and configure an API within an API Management service instance. | `Microsoft.ApiManagement/service/apis` | [2022-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2022-08-01/service/apis) | | `Microsoft.ApiManagement/service/apis/diagnostics` | [2022-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2022-08-01/service/apis/diagnostics) | | `Microsoft.ApiManagement/service/apis/policies` | [2022-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2022-08-01/service/apis/policies) | -| `Microsoft.Web/sites/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | +| `Microsoft.Web/sites/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-09-01/sites/config) | ## Usage examples diff --git a/avm/ptn/azd/container-app-upsert/README.md b/avm/ptn/azd/container-app-upsert/README.md index 5caa1cec82..8de71526cd 100644 --- a/avm/ptn/azd/container-app-upsert/README.md +++ b/avm/ptn/azd/container-app-upsert/README.md @@ -609,7 +609,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/ptn/azd/acr-container-app:0.1.0` | Remote reference | +| `br/public:avm/ptn/azd/acr-container-app:0.1.1` | Remote reference | ## Data Collection diff --git a/avm/ptn/azd/container-app-upsert/main.bicep b/avm/ptn/azd/container-app-upsert/main.bicep index 17533fdf52..955ec4ad2b 100644 --- a/avm/ptn/azd/container-app-upsert/main.bicep +++ b/avm/ptn/azd/container-app-upsert/main.bicep @@ -113,7 +113,7 @@ resource existingApp 'Microsoft.App/containerApps@2023-05-02-preview' existing = name: name } -module app 'br/public:avm/ptn/azd/acr-container-app:0.1.0' = { +module app 'br/public:avm/ptn/azd/acr-container-app:0.1.1' = { name: '${uniqueString(deployment().name, location)}-container-app-update' params: { name: name diff --git a/avm/ptn/azd/container-app-upsert/main.json b/avm/ptn/azd/container-app-upsert/main.json index 087916758f..0436809e07 100644 --- a/avm/ptn/azd/container-app-upsert/main.json +++ b/avm/ptn/azd/container-app-upsert/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "610733373146441190" + "version": "0.30.23.60470", + "templateHash": "4957977967131806012" }, "name": "Azd Container App Upsert", "description": "Creates or updates an existing Azure Container App.\n\n**Note:** This module is not intended for broad, generic use, as it was designed to cater for the requirements of the AZD CLI product. Feature requests and bug fix requests are welcome if they support the development of the AZD CLI but may not be incorporated if they aim to make this module more generic than what it needs to be for its primary use case", @@ -361,7 +361,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "1832494856594008897" + "templateHash": "13777874990841344112" }, "name": "Azd ACR Linked Container App", "description": "Creates a container app in an Azure Container App environment.\n\n**Note:** This module is not intended for broad, generic use, as it was designed to cater for the requirements of the AZD CLI product. Feature requests and bug fix requests are welcome if they support the development of the AZD CLI but may not be incorporated if they aim to make this module more generic than what it needs to be for its primary use case", @@ -657,7 +657,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.ptn.azd-acrcontainerapp.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.ptn.azd-acrcontainerapp.{0}.{1}', replace('0.1.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1784,7 +1784,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "11140098273900072819" + "templateHash": "676465844790879977" }, "name": "ACR Pull permissions", "description": "Assigns ACR Pull permissions to access an Azure Container Registry.", @@ -1818,7 +1818,7 @@ { "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "acrpullrole-deployment", + "name": "[guid(subscription().id, resourceGroup().id, parameters('principalId'), variables('acrPullRole'))]", "properties": { "expressionEvaluationOptions": { "scope": "inner" diff --git a/avm/ptn/data/private-analytical-workspace/README.md b/avm/ptn/data/private-analytical-workspace/README.md new file mode 100644 index 0000000000..2361e5b719 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/README.md @@ -0,0 +1,2038 @@ +# private-analytical-workspace `[Data/PrivateAnalyticalWorkspace]` + +This pattern module enables you to use Azure services that are typical for data analytics solutions. The goal is to help data scientists establish an environment for data analysis simply. It is secure by default for enterprise use. Data scientists should not spend much time on how to build infrastructure solution. They should mainly concentrate on the data analytics components they require for the solution. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Notes](#Notes) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Databricks/accessConnectors` | [2022-10-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Databricks/2022-10-01-preview/accessConnectors) | +| `Microsoft.Databricks/workspaces` | [2024-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Databricks/2024-05-01/workspaces) | +| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | +| `Microsoft.KeyVault/vaults` | [2022-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2022-07-01/vaults) | +| `Microsoft.KeyVault/vaults/accessPolicies` | [2022-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2022-07-01/vaults/accessPolicies) | +| `Microsoft.KeyVault/vaults/keys` | [2022-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2022-07-01/vaults/keys) | +| `Microsoft.KeyVault/vaults/secrets` | [2022-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2022-07-01/vaults/secrets) | +| `Microsoft.Network/networkSecurityGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/networkSecurityGroups) | +| `Microsoft.Network/privateDnsZones` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones) | +| `Microsoft.Network/privateDnsZones/A` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/A) | +| `Microsoft.Network/privateDnsZones/AAAA` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/AAAA) | +| `Microsoft.Network/privateDnsZones/CNAME` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/CNAME) | +| `Microsoft.Network/privateDnsZones/MX` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/MX) | +| `Microsoft.Network/privateDnsZones/PTR` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/PTR) | +| `Microsoft.Network/privateDnsZones/SOA` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SOA) | +| `Microsoft.Network/privateDnsZones/SRV` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SRV) | +| `Microsoft.Network/privateDnsZones/TXT` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/TXT) | +| `Microsoft.Network/privateDnsZones/virtualNetworkLinks` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/virtualNetworkLinks) | +| `Microsoft.Network/privateEndpoints` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints) | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints/privateDnsZoneGroups) | +| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks) | +| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/subnets) | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/virtualNetworkPeerings) | +| `Microsoft.OperationalInsights/workspaces` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2022-10-01/workspaces) | +| `Microsoft.OperationalInsights/workspaces/dataExports` | [2020-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/dataExports) | +| `Microsoft.OperationalInsights/workspaces/dataSources` | [2020-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/dataSources) | +| `Microsoft.OperationalInsights/workspaces/linkedServices` | [2020-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/linkedServices) | +| `Microsoft.OperationalInsights/workspaces/linkedStorageAccounts` | [2020-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/linkedStorageAccounts) | +| `Microsoft.OperationalInsights/workspaces/savedSearches` | [2020-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/savedSearches) | +| `Microsoft.OperationalInsights/workspaces/storageInsightConfigs` | [2020-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/storageInsightConfigs) | +| `Microsoft.OperationalInsights/workspaces/tables` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2022-10-01/workspaces/tables) | +| `Microsoft.OperationsManagement/solutions` | [2015-11-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationsManagement/2015-11-01-preview/solutions) | + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/ptn/data/private-analytical-workspace:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [Minimal Deployment - fully private](#example-3-minimal-deployment---fully-private) +- [Minimal Deployment - allowed IP address](#example-4-minimal-deployment---allowed-ip-address) +- [Use Case 1 - fully private](#example-5-use-case-1---fully-private) +- [Use Case 1 - allowed IP address](#example-6-use-case-1---allowed-ip-address) +- [Use Case 2 - fully private](#example-7-use-case-2---fully-private) +- [Use Case 2 - allowed IP address](#example-8-use-case-2---allowed-ip-address) +- [Use Case 3 - fully private](#example-9-use-case-3---fully-private) +- [Use Case 3 - allowed IP address](#example-10-use-case-3---allowed-ip-address) +- [WAF-aligned](#example-11-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawmin002' + // Non-required parameters + advancedOptions: { + keyVault: { + enablePurgeProtection: false + } + } + } +} +``` + +
+

+ +

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

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawmin002' +// Non-required parameters +param advancedOptions = { + keyVault: { + enablePurgeProtection: false + } +} +``` + +
+

+ +### Example 2: _Using large parameter set_ + +This instance deploys the module with most of its features enabled. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawmax002' + // Non-required parameters + advancedOptions: { + keyVault: { + createMode: 'default' + enablePurgeProtection: false + enableSoftDelete: false + sku: 'standard' + softDeleteRetentionInDays: 7 + } + logAnalyticsWorkspace: { + dailyQuotaGb: 1 + dataRetention: 35 + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } + } + enableDatabricks: true + location: '' + tags: { + CostCenter: '123459876' + Owner: 'Contoso MAX Team' + } + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawmax002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "keyVault": { + "createMode": "default", + "enablePurgeProtection": false, + "enableSoftDelete": false, + "sku": "standard", + "softDeleteRetentionInDays": 7 + }, + "logAnalyticsWorkspace": { + "dailyQuotaGb": 1, + "dataRetention": 35 + }, + "networkAcls": { + "ipRules": [ + "104.43.16.94" + ] + } + } + }, + "enableDatabricks": { + "value": true + }, + "location": { + "value": "" + }, + "tags": { + "value": { + "CostCenter": "123459876", + "Owner": "Contoso MAX Team" + } + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawmax002' +// Non-required parameters +param advancedOptions = { + keyVault: { + createMode: 'default' + enablePurgeProtection: false + enableSoftDelete: false + sku: 'standard' + softDeleteRetentionInDays: 7 + } + logAnalyticsWorkspace: { + dailyQuotaGb: 1 + dataRetention: 35 + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } +} +param enableDatabricks = true +param location = '' +param tags = { + CostCenter: '123459876' + Owner: 'Contoso MAX Team' +} +``` + +
+

+ +### Example 3: _Minimal Deployment - fully private_ + +Isolated network deployment (Minimalistic) - fully private. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawminpriv002' + // Non-required parameters + advancedOptions: { + keyVault: { + enablePurgeProtection: false + } + } + enableDatabricks: false + tags: { + CostCenter: '123-456-789' + Owner: 'Contoso' + } + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawminpriv002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "keyVault": { + "enablePurgeProtection": false + } + } + }, + "enableDatabricks": { + "value": false + }, + "tags": { + "value": { + "CostCenter": "123-456-789", + "Owner": "Contoso" + } + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawminpriv002' +// Non-required parameters +param advancedOptions = { + keyVault: { + enablePurgeProtection: false + } +} +param enableDatabricks = false +param tags = { + CostCenter: '123-456-789' + Owner: 'Contoso' +} +``` + +
+

+ +### Example 4: _Minimal Deployment - allowed IP address_ + +Isolated network deployment (Minimalistic) - allowed IP address. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawminpu002' + // Non-required parameters + advancedOptions: { + keyVault: { + enablePurgeProtection: false + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } + } + enableDatabricks: false + tags: { + CostCenter: '123-456-789' + Owner: 'Contoso' + } + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawminpu002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "keyVault": { + "enablePurgeProtection": false + }, + "networkAcls": { + "ipRules": [ + "104.43.16.94" + ] + } + } + }, + "enableDatabricks": { + "value": false + }, + "tags": { + "value": { + "CostCenter": "123-456-789", + "Owner": "Contoso" + } + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawminpu002' +// Non-required parameters +param advancedOptions = { + keyVault: { + enablePurgeProtection: false + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } +} +param enableDatabricks = false +param tags = { + CostCenter: '123-456-789' + Owner: 'Contoso' +} +``` + +
+

+ +### Example 5: _Use Case 1 - fully private_ + +Isolated network deployment - fully private. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawu1pr002' + // Non-required parameters + advancedOptions: { + keyVault: { + enablePurgeProtection: false + } + } + enableDatabricks: true + tags: { + CostCenter: '123-456-789' + Owner: 'Contoso' + } + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawu1pr002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "keyVault": { + "enablePurgeProtection": false + } + } + }, + "enableDatabricks": { + "value": true + }, + "tags": { + "value": { + "CostCenter": "123-456-789", + "Owner": "Contoso" + } + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawu1pr002' +// Non-required parameters +param advancedOptions = { + keyVault: { + enablePurgeProtection: false + } +} +param enableDatabricks = true +param tags = { + CostCenter: '123-456-789' + Owner: 'Contoso' +} +``` + +
+

+ +### Example 6: _Use Case 1 - allowed IP address_ + +Isolated network deployment - allowed IP address. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawu1pu002' + // Non-required parameters + advancedOptions: { + keyVault: { + enablePurgeProtection: false + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } + } + enableDatabricks: true + tags: { + CostCenter: '123-456-789' + Owner: 'Contoso' + } + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawu1pu002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "keyVault": { + "enablePurgeProtection": false + }, + "networkAcls": { + "ipRules": [ + "104.43.16.94" + ] + } + } + }, + "enableDatabricks": { + "value": true + }, + "tags": { + "value": { + "CostCenter": "123-456-789", + "Owner": "Contoso" + } + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawu1pu002' +// Non-required parameters +param advancedOptions = { + keyVault: { + enablePurgeProtection: false + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } +} +param enableDatabricks = true +param tags = { + CostCenter: '123-456-789' + Owner: 'Contoso' +} +``` + +
+

+ +### Example 7: _Use Case 2 - fully private_ + +Deployment in an Existing, Enterprise-Specific Virtual Network - fully private. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawu2pr002' + // Non-required parameters + advancedOptions: { + databricks: { + subnetNameBackend: '' + subnetNameFrontend: '' + } + keyVault: { + enablePurgeProtection: false + } + virtualNetwork: { + subnetNamePrivateLink: '' + } + } + enableDatabricks: true + tags: { + CostCenter: '123-456-789' + Owner: 'Contoso' + } + virtualNetworkResourceId: '' + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawu2pr002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "databricks": { + "subnetNameBackend": "", + "subnetNameFrontend": "" + }, + "keyVault": { + "enablePurgeProtection": false + }, + "virtualNetwork": { + "subnetNamePrivateLink": "" + } + } + }, + "enableDatabricks": { + "value": true + }, + "tags": { + "value": { + "CostCenter": "123-456-789", + "Owner": "Contoso" + } + }, + "virtualNetworkResourceId": { + "value": "" + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawu2pr002' +// Non-required parameters +param advancedOptions = { + databricks: { + subnetNameBackend: '' + subnetNameFrontend: '' + } + keyVault: { + enablePurgeProtection: false + } + virtualNetwork: { + subnetNamePrivateLink: '' + } +} +param enableDatabricks = true +param tags = { + CostCenter: '123-456-789' + Owner: 'Contoso' +} +param virtualNetworkResourceId = '' +``` + +
+

+ +### Example 8: _Use Case 2 - allowed IP address_ + +Deployment in an Existing, Enterprise-Specific Virtual Network - allowed IP address. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawu2pu002' + // Non-required parameters + advancedOptions: { + databricks: { + subnetNameBackend: '' + subnetNameFrontend: '' + } + keyVault: { + enablePurgeProtection: false + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } + virtualNetwork: { + subnetNamePrivateLink: '' + } + } + enableDatabricks: true + tags: { + CostCenter: '123-456-789' + Owner: 'Contoso' + } + virtualNetworkResourceId: '' + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawu2pu002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "databricks": { + "subnetNameBackend": "", + "subnetNameFrontend": "" + }, + "keyVault": { + "enablePurgeProtection": false + }, + "networkAcls": { + "ipRules": [ + "104.43.16.94" + ] + }, + "virtualNetwork": { + "subnetNamePrivateLink": "" + } + } + }, + "enableDatabricks": { + "value": true + }, + "tags": { + "value": { + "CostCenter": "123-456-789", + "Owner": "Contoso" + } + }, + "virtualNetworkResourceId": { + "value": "" + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawu2pu002' +// Non-required parameters +param advancedOptions = { + databricks: { + subnetNameBackend: '' + subnetNameFrontend: '' + } + keyVault: { + enablePurgeProtection: false + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } + virtualNetwork: { + subnetNamePrivateLink: '' + } +} +param enableDatabricks = true +param tags = { + CostCenter: '123-456-789' + Owner: 'Contoso' +} +param virtualNetworkResourceId = '' +``` + +
+

+ +### Example 9: _Use Case 3 - fully private_ + +Integration with existing core Infrastructure - fully private. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawu3pr002' + // Non-required parameters + advancedOptions: { + databricks: { + subnetNameBackend: '' + subnetNameFrontend: '' + } + keyVault: { + enablePurgeProtection: false + } + virtualNetwork: { + subnetNamePrivateLink: '' + } + } + enableDatabricks: true + keyVaultResourceId: '' + logAnalyticsWorkspaceResourceId: '' + tags: { + CostCenter: '123-456-789' + Owner: 'Contoso' + } + virtualNetworkResourceId: '' + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawu3pr002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "databricks": { + "subnetNameBackend": "", + "subnetNameFrontend": "" + }, + "keyVault": { + "enablePurgeProtection": false + }, + "virtualNetwork": { + "subnetNamePrivateLink": "" + } + } + }, + "enableDatabricks": { + "value": true + }, + "keyVaultResourceId": { + "value": "" + }, + "logAnalyticsWorkspaceResourceId": { + "value": "" + }, + "tags": { + "value": { + "CostCenter": "123-456-789", + "Owner": "Contoso" + } + }, + "virtualNetworkResourceId": { + "value": "" + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawu3pr002' +// Non-required parameters +param advancedOptions = { + databricks: { + subnetNameBackend: '' + subnetNameFrontend: '' + } + keyVault: { + enablePurgeProtection: false + } + virtualNetwork: { + subnetNamePrivateLink: '' + } +} +param enableDatabricks = true +param keyVaultResourceId = '' +param logAnalyticsWorkspaceResourceId = '' +param tags = { + CostCenter: '123-456-789' + Owner: 'Contoso' +} +param virtualNetworkResourceId = '' +``` + +
+

+ +### Example 10: _Use Case 3 - allowed IP address_ + +Integration with existing core Infrastructure - allowed IP address. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawu3p002' + // Non-required parameters + advancedOptions: { + databricks: { + subnetNameBackend: '' + subnetNameFrontend: '' + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } + virtualNetwork: { + subnetNamePrivateLink: '' + } + } + enableDatabricks: true + keyVaultResourceId: '' + logAnalyticsWorkspaceResourceId: '' + tags: { + CostCenter: '123-456-789' + Owner: 'Contoso' + } + virtualNetworkResourceId: '' + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawu3p002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "databricks": { + "subnetNameBackend": "", + "subnetNameFrontend": "" + }, + "networkAcls": { + "ipRules": [ + "104.43.16.94" + ] + }, + "virtualNetwork": { + "subnetNamePrivateLink": "" + } + } + }, + "enableDatabricks": { + "value": true + }, + "keyVaultResourceId": { + "value": "" + }, + "logAnalyticsWorkspaceResourceId": { + "value": "" + }, + "tags": { + "value": { + "CostCenter": "123-456-789", + "Owner": "Contoso" + } + }, + "virtualNetworkResourceId": { + "value": "" + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawu3p002' +// Non-required parameters +param advancedOptions = { + databricks: { + subnetNameBackend: '' + subnetNameFrontend: '' + } + networkAcls: { + ipRules: [ + '104.43.16.94' + ] + } + virtualNetwork: { + subnetNamePrivateLink: '' + } +} +param enableDatabricks = true +param keyVaultResourceId = '' +param logAnalyticsWorkspaceResourceId = '' +param tags = { + CostCenter: '123-456-789' + Owner: 'Contoso' +} +param virtualNetworkResourceId = '' +``` + +
+

+ +### Example 11: _WAF-aligned_ + +This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. + + +

+ +via Bicep module + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'privateAnalyticalWorkspaceDeployment' + params: { + // Required parameters + name: 'dpawwaf002' + // Non-required parameters + advancedOptions: { + keyVault: { + createMode: 'default' + enablePurgeProtection: false + enableSoftDelete: true + sku: 'standard' + softDeleteRetentionInDays: 90 + } + logAnalyticsWorkspace: { + dailyQuotaGb: 1 + dataRetention: 35 + } + } + enableDatabricks: true + enableTelemetry: true + location: '' + tags: { + CostCenter: '123-456-789' + 'hidden-title': 'This is visible in the resource name' + Owner: 'Contoso' + } + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dpawwaf002" + }, + // Non-required parameters + "advancedOptions": { + "value": { + "keyVault": { + "createMode": "default", + "enablePurgeProtection": false, + "enableSoftDelete": true, + "sku": "standard", + "softDeleteRetentionInDays": 90 + }, + "logAnalyticsWorkspace": { + "dailyQuotaGb": 1, + "dataRetention": 35 + } + } + }, + "enableDatabricks": { + "value": true + }, + "enableTelemetry": { + "value": true + }, + "location": { + "value": "" + }, + "tags": { + "value": { + "CostCenter": "123-456-789", + "hidden-title": "This is visible in the resource name", + "Owner": "Contoso" + } + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/data/private-analytical-workspace:' + +// Required parameters +param name = 'dpawwaf002' +// Non-required parameters +param advancedOptions = { + keyVault: { + createMode: 'default' + enablePurgeProtection: false + enableSoftDelete: true + sku: 'standard' + softDeleteRetentionInDays: 90 + } + logAnalyticsWorkspace: { + dailyQuotaGb: 1 + dataRetention: 35 + } +} +param enableDatabricks = true +param enableTelemetry = true +param location = '' +param tags = { + CostCenter: '123-456-789' + 'hidden-title': 'This is visible in the resource name' + Owner: 'Contoso' +} +``` + +
+

+ +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the private analytical workspace solution and its components. Used to ensure unique resource names. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`advancedOptions`](#parameter-advancedoptions) | object | Additional options that can affect some components of the solution and how they are configured. | +| [`enableDatabricks`](#parameter-enabledatabricks) | bool | Enable/Disable Azure Databricks service within the solution. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`keyVaultResourceId`](#parameter-keyvaultresourceid) | string | If you already have a Key Vault that you want to use with the solution, you can specify it here. Otherwise, this module will create a new Key Vault for you. | +| [`location`](#parameter-location) | string | Location for all Resources in the solution. | +| [`lock`](#parameter-lock) | object | The lock settings for all Resources in the solution. | +| [`logAnalyticsWorkspaceResourceId`](#parameter-loganalyticsworkspaceresourceid) | string | If you already have a Log Analytics Workspace that you want to use with the solution, you can specify it here. Otherwise, this module will create a new Log Analytics Workspace for you. | +| [`solutionAdministrators`](#parameter-solutionadministrators) | array | Array of users or groups who are in charge of the solution. | +| [`tags`](#parameter-tags) | object | Tags for all Resources in the solution. | +| [`virtualNetworkResourceId`](#parameter-virtualnetworkresourceid) | string | This option allows the solution to be connected to a VNET that the customer provides. If you have an existing VNET that was made for this solution, you can specify it here. If you do not use this option, this module will make a new VNET for you. | + +### Parameter: `name` + +Name of the private analytical workspace solution and its components. Used to ensure unique resource names. + +- Required: Yes +- Type: string + +### Parameter: `advancedOptions` + +Additional options that can affect some components of the solution and how they are configured. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`databricks`](#parameter-advancedoptionsdatabricks) | object | This parameter allows you to specify additional settings for Azure Databricks if you set the 'enableDatabricks' parameter to 'true'. | +| [`keyVault`](#parameter-advancedoptionskeyvault) | object | This parameter allows you to specify additional settings for Azure Key Vault if the 'keyVaultResourceId' parameter is empty. | +| [`logAnalyticsWorkspace`](#parameter-advancedoptionsloganalyticsworkspace) | object | This parameter allows you to specify additional settings for Azure Log Analytics Workspace if the 'logAnalyticsWorkspaceResourceId' parameter is empty. | +| [`networkAcls`](#parameter-advancedoptionsnetworkacls) | object | Networks Access Control Lists. This value has public IP addresses or ranges that are allowed to access resources in the solution. | +| [`virtualNetwork`](#parameter-advancedoptionsvirtualnetwork) | object | You can use this parameter to integrate the solution with an existing Azure Virtual Network if the 'virtualNetworkResourceId' parameter is not empty. | + +### Parameter: `advancedOptions.databricks` + +This parameter allows you to specify additional settings for Azure Databricks if you set the 'enableDatabricks' parameter to 'true'. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetNameBackend`](#parameter-advancedoptionsdatabrickssubnetnamebackend) | string | The name of the existing backend Subnet for Azure Databricks within the Virtual Network in the parameter: 'virtualNetworkResourceId'. | +| [`subnetNameFrontend`](#parameter-advancedoptionsdatabrickssubnetnamefrontend) | string | The name of the existing frontend Subnet for Azure Databricks within the Virtual Network in the parameter: 'virtualNetworkResourceId'. | + +### Parameter: `advancedOptions.databricks.subnetNameBackend` + +The name of the existing backend Subnet for Azure Databricks within the Virtual Network in the parameter: 'virtualNetworkResourceId'. + +- Required: No +- Type: string + +### Parameter: `advancedOptions.databricks.subnetNameFrontend` + +The name of the existing frontend Subnet for Azure Databricks within the Virtual Network in the parameter: 'virtualNetworkResourceId'. + +- Required: No +- Type: string + +### Parameter: `advancedOptions.keyVault` + +This parameter allows you to specify additional settings for Azure Key Vault if the 'keyVaultResourceId' parameter is empty. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`createMode`](#parameter-advancedoptionskeyvaultcreatemode) | string | The vault's create mode to indicate whether the vault need to be recovered or not. The default value is: 'default'. | +| [`enablePurgeProtection`](#parameter-advancedoptionskeyvaultenablepurgeprotection) | bool | Provide 'true' to enable Key Vault's purge protection feature. The default value is: 'true'. | +| [`enableSoftDelete`](#parameter-advancedoptionskeyvaultenablesoftdelete) | bool | Switch to enable/disable Key Vault's soft delete feature. The default value is: 'true'. | +| [`sku`](#parameter-advancedoptionskeyvaultsku) | string | Specifies the SKU for the vault. The default value is: 'premium'. | +| [`softDeleteRetentionInDays`](#parameter-advancedoptionskeyvaultsoftdeleteretentionindays) | int | Soft delete data retention days. It accepts >=7 and <=90. The default value is: '90'. | + +### Parameter: `advancedOptions.keyVault.createMode` + +The vault's create mode to indicate whether the vault need to be recovered or not. The default value is: 'default'. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'default' + 'recover' + ] + ``` + +### Parameter: `advancedOptions.keyVault.enablePurgeProtection` + +Provide 'true' to enable Key Vault's purge protection feature. The default value is: 'true'. + +- Required: No +- Type: bool + +### Parameter: `advancedOptions.keyVault.enableSoftDelete` + +Switch to enable/disable Key Vault's soft delete feature. The default value is: 'true'. + +- Required: No +- Type: bool + +### Parameter: `advancedOptions.keyVault.sku` + +Specifies the SKU for the vault. The default value is: 'premium'. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'premium' + 'standard' + ] + ``` + +### Parameter: `advancedOptions.keyVault.softDeleteRetentionInDays` + +Soft delete data retention days. It accepts >=7 and <=90. The default value is: '90'. + +- Required: No +- Type: int + +### Parameter: `advancedOptions.logAnalyticsWorkspace` + +This parameter allows you to specify additional settings for Azure Log Analytics Workspace if the 'logAnalyticsWorkspaceResourceId' parameter is empty. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`dailyQuotaGb`](#parameter-advancedoptionsloganalyticsworkspacedailyquotagb) | int | The workspace daily quota for ingestion. The default value is: '-1' (not limited). | +| [`dataRetention`](#parameter-advancedoptionsloganalyticsworkspacedataretention) | int | Number of days data will be retained for. The default value is: '365'. | + +### Parameter: `advancedOptions.logAnalyticsWorkspace.dailyQuotaGb` + +The workspace daily quota for ingestion. The default value is: '-1' (not limited). + +- Required: No +- Type: int + +### Parameter: `advancedOptions.logAnalyticsWorkspace.dataRetention` + +Number of days data will be retained for. The default value is: '365'. + +- Required: No +- Type: int + +### Parameter: `advancedOptions.networkAcls` + +Networks Access Control Lists. This value has public IP addresses or ranges that are allowed to access resources in the solution. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`ipRules`](#parameter-advancedoptionsnetworkaclsiprules) | array | Sets the public IP addresses or ranges that are allowed to access resources in the solution. | + +### Parameter: `advancedOptions.networkAcls.ipRules` + +Sets the public IP addresses or ranges that are allowed to access resources in the solution. + +- Required: No +- Type: array + +### Parameter: `advancedOptions.virtualNetwork` + +You can use this parameter to integrate the solution with an existing Azure Virtual Network if the 'virtualNetworkResourceId' parameter is not empty. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetNamePrivateLink`](#parameter-advancedoptionsvirtualnetworksubnetnameprivatelink) | string | The name of the existing Private Link Subnet within the Virtual Network in the parameter: 'virtualNetworkResourceId'. | + +### Parameter: `advancedOptions.virtualNetwork.subnetNamePrivateLink` + +The name of the existing Private Link Subnet within the Virtual Network in the parameter: 'virtualNetworkResourceId'. + +- Required: No +- Type: string + +### Parameter: `enableDatabricks` + +Enable/Disable Azure Databricks service within the solution. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `keyVaultResourceId` + +If you already have a Key Vault that you want to use with the solution, you can specify it here. Otherwise, this module will create a new Key Vault for you. + +- Required: No +- Type: string + +### Parameter: `location` + +Location for all Resources in the solution. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings for all Resources in the solution. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `logAnalyticsWorkspaceResourceId` + +If you already have a Log Analytics Workspace that you want to use with the solution, you can specify it here. Otherwise, this module will create a new Log Analytics Workspace for you. + +- Required: No +- Type: string + +### Parameter: `solutionAdministrators` + +Array of users or groups who are in charge of the solution. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-solutionadministratorsprincipalid) | string | The principal ID of the principal (user/group) to assign the role to. | +| [`principalType`](#parameter-solutionadministratorsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `solutionAdministrators.principalId` + +The principal ID of the principal (user/group) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `solutionAdministrators.principalType` + +The principal type of the assigned principal ID. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Group' + 'User' + ] + ``` + +### Parameter: `tags` + +Tags for all Resources in the solution. + +- Required: No +- Type: object + +### Parameter: `virtualNetworkResourceId` + +This option allows the solution to be connected to a VNET that the customer provides. If you have an existing VNET that was made for this solution, you can specify it here. If you do not use this option, this module will make a new VNET for you. + +- Required: No +- Type: string + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `databricksLocation` | string | Conditional. The location of the Azure Databricks when `enableDatabricks` is `true`. | +| `databricksName` | string | Conditional. The name of the Azure Databricks when `enableDatabricks` is `true`. | +| `databricksResourceGroupName` | string | Conditional. The name of the Azure Databricks resource group when `enableDatabricks` is `true`. | +| `databricksResourceId` | string | Conditional. The resource ID of the Azure Databricks when `enableDatabricks` is `true`. | +| `keyVaultLocation` | string | The location of the Azure Key Vault. | +| `keyVaultName` | string | The name of the Azure Key Vault. | +| `keyVaultResourceGroupName` | string | The name of the Azure Key Vault resource group. | +| `keyVaultResourceId` | string | The resource ID of the Azure Key Vault. | +| `location` | string | The location the resource was deployed into. | +| `logAnalyticsWorkspaceLocation` | string | The location of the Azure Log Analytics Workspace. | +| `logAnalyticsWorkspaceName` | string | The name of the Azure Log Analytics Workspace. | +| `logAnalyticsWorkspaceResourceGroupName` | string | The name of the Azure Log Analytics Workspace resource group. | +| `logAnalyticsWorkspaceResourceId` | string | The resource ID of the Azure Log Analytics Workspace. | +| `name` | string | The name of the resource. | +| `resourceGroupName` | string | The name of the managed resource group. | +| `resourceId` | string | The resource ID of the resource. | +| `virtualNetworkLocation` | string | The location of the Azure Virtual Network. | +| `virtualNetworkName` | string | The name of the Azure Virtual Network. | +| `virtualNetworkResourceGroupName` | string | The name of the Azure Virtual Network resource group. | +| `virtualNetworkResourceId` | string | The resource ID of the Azure Virtual Network. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/res/databricks/access-connector:0.3.0` | Remote reference | +| `br/public:avm/res/databricks/workspace:0.8.5` | Remote reference | +| `br/public:avm/res/key-vault/vault:0.9.0` | Remote reference | +| `br/public:avm/res/network/network-security-group:0.5.0` | Remote reference | +| `br/public:avm/res/network/private-dns-zone:0.5.0` | Remote reference | +| `br/public:avm/res/network/private-dns-zone:0.6.0` | Remote reference | +| `br/public:avm/res/network/virtual-network:0.5.0` | Remote reference | +| `br/public:avm/res/operational-insights/workspace:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + +## Notes + +This pattern aims to speed up data science projects and create Azure environments +for data analysis in a secure and enterprise-ready way. + +Data scientists should not worry about infrastructure details.
+Ideally, data scientists should only focus on the data analytics tools they need for the solution. For example Databricks, Machine learning, database, etc.
+Enterprise security, monitoring, secrets storage, databases, access over a private network should be built into the solution in a transparent way so cloud and security team can approve the whole solution easily. + +One of the design goals of this pattern is to have all the services that are part of the solution +connected to one virtual network to make the traffic between services private (use of private endpoints). +A virtual network can be either created along with the solution or +an existing / pre-defined virtual network (Hub/Spoke model – spoke VNET made by network enterprise team) can be chosen. + +The solution's services save diagnostics data to Azure Log Analytics Workspace, +either created along with the solution or an existing / pre-defined. +Secrets such as connection string or data source credentials should +go to secrets store securely. Analytical tools use secure credentials to access data sources. +Secrets can go to Azure Key Vault, either existing or new. + +The solution will include at least a virtual network (either created or using VNET created +by enterprise network team), Azure Log Analytics workspace for diagnostics and monitoring +(either created or given by cloud team) and Azure Key Vault as secrets +store (either created or given by cloud team). + +Every resource in the solution can be tagged and locked. +The owner role for every resource can be given with the ```solutionAdministrators.*``` parameter.
+All resources are named according to the provided input parameter ```name```.
+All resources gather diagnostic and monitoring data, which is then stored in either a newly created or an existing Log Analytics Workspace. + +The solution may optionally include additional analytical services, for instance by enabling the ```enableDatabricks``` parameter.
+The parameter ```advancedOptions.*``` allows for finer customization of the solution. +Certain Azure services within the solution can be reached via a public endpoint (if preferred) and can also be limited using network access control lists by permitting only the public IP of the accessing client. + +This solution invariably demands a Virtual network presence. +At the very least, it necessitates a single subnet to cater to private link endpoints. +The incorporation of additional optional services implies further prerequisites for the network, +such as subnets, their sizes, network security groups, NSG access control lists, (sometimes) private endpoints, DNS zones, etc. +For instance, activating the Azure Databricks service would automatically generate a virtual network and its essential components per established best practices.
+When an enterprise's virtual network is supplied by either the network or cloud team, it has to comply with the requirements of the services being activated. +It's crucial that Network Security Groups, Network Security Group Rules, DNS Zones and DNS forwarding, (sometimes) private endpoints, and domain zones for services like Key Vault and Azure Databricks, along with subnet delegations, are all set up correctly. +For example, refer to the documentation here: https://learn.microsoft.com/en-us/azure/databricks/security/network/classic/vnet-inject#--virtual-network-requirements. + +### Supported Use Cases + +#### Use Case 1: Greenfield, isolated network deployment + +This use case is fairly simple to provision while ensuring security. +Ideal for rapid problem-solving that requires an analytical workspace for swift development. +The solution will create all the required components such as Virtual Network, Monitoring, Key Vault, permissions, and analytical services. +All utilizing recommended practices. + +Because of the isolated network configuration, public IP addresses of customers must be designated as authorized to access the environment through secure public endpoints. +The solution will only be accessible from predetermined public IP addresses. This use case may not be suitable for highly restrictive enterprises that have strict no public IP policies.
+The identity of the solution administrator or the managing group must be submitted to gain access and control over the solution. +There is no requirement to pre-establish a virtual network or any additional components. + +##### Virtual Network + +A Virtual Network will be created with all necessary components and will be established to accommodate the designated Azure Services. +This will include the creation of appropriate subnets, private links, and Network Security Groups. +Additionally, it will leverage Azure DNS along with Azure DNS zones for the configuration of private endpoints, which will be associated with the Virtual Network. + +The assigned IP address range of a Virtual Network may conflict with that of an enterprise network. As a result, this virtual network should not be connected, or peered, with any enterprise network. In this use case, the virtual network is established as an isolated segment. + +Since it's an isolated segment, in order to access client resources such as key vault and others, the client's public IP must be included in the allowed range within the ```advancedOptions.networkAcls.ipRules``` parameter. + +For a dedicated virtual network to be provisioned for you (this use case), the Virtual Network ```virtualNetworkResourceId``` parameter needs to remain unfilled. + + +##### Monitoring of the Solution + +If the parameter ```logAnalyticsWorkspaceResourceId``` is left unspecified or set to ```null```, a new Azure Log Analytics Workspace will be created as part of the solution. The diagnostic settings for most services within the solution will be configured to channel into this newly created Azure Log Analytics Workspace.
+Additional creation configurations for the Azure Log Analytics Workspace are available under the parameter ```advancedOptions.logAnalyticsWorkspace.*```.
+The ```logAnalyticsWorkspaceResourceId``` parameter may be configured to use an existing Azure Log Analytics Workspace, which is beneficial for enterprises that prefer to centralize their diagnostic data.
+ + +##### Storing Secrets - Key Vault + +If the parameter ```keyVaultResourceId``` is left unspecified or set to ```null```, a new Azure Key Vault will be created as part of the solution.
+Additional creation configurations for the Azure Key Vault are available under the parameter ```advancedOptions.keyVault.*```.
+As part of the solution, a private endpoint and a DNS Key Vault Zone are created. To handle secrets through the Azure Portal, Public Access must be provided for the given public IP within the parameter ```advancedOptions.networkAcls.ipRules```.
+For the handling of secrets, users need to have privileged roles. Those listed in the ```solutionAdministrators.*``` parameter will receive 'Key Vault Administrator' privileges specifically for Azure Key Vaults that are newly created.
+ + +##### Solution Administrators + +In order to grant administrative rights for the newly created services that have been added to the solution, you should utilize the parameter ```solutionAdministrators.*```. You can designate User or Entra ID Groups for this purpose.
+The specified identities will be granted ownership of the solution, enabling them to delegate permissions as necessary. Additionally, they will obtain 'Key Vault Administrator' rights, which apply solely to the Azure Key Vaults that have been created as part of the solution.
+It's essential to designate an individual as the Solution Administrator to utilize the solution effectively.
+ + +##### Analytical Service - Azure Databricks + +If the parameter ```enableDatabricks``` is set to ```true```, a new Azure Databricks instance will be created as part of the solution.
+Additional creation configurations for the Azure Databricks are available under the parameter ```advancedOptions.databricks.*```.
+As part of the solution, two subnets with delegations, two private endpoints, network security groups and a Azure Databricks Zone are created.
+To access Azure Databricks integrated into the isolated Virtual Network, Public Access must be provided for the given public IP within the parameter ```advancedOptions.networkAcls.ipRules```.
+Additional manual setup is required to restrict public access for different clients. Refer to this guide for more information:
+ +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'UC1' + params: { + // Required parameters + name: 'pawuc1' + // Non-required parameters + virtualNetworkResourceId: null // null means new VNET will be created + logAnalyticsWorkspaceResourceId: null // null means new Log Analytical Workspace will be created + keyVaultResourceId: null // null means new Azure key Vault will be created + enableDatabricks: true // Part of the solution and VNET will be new instance of the Azure Databricks + solutionAdministrators: [ + { + principalId: // Specified group will have enough permissions to manage the solution + principalType: 'Group' // Group and/or User type can be specified + } + ] + advancedOptions: { + networkAcls: { ipRules: [] } // Which public IP addresses of the end users can access the isolated solution (enables public endpoints for some services) + } + tags: { Owner: 'Contoso', 'Cost Center': '2345-324' } + } +} +``` + + +#### Use Case 2: Brownfield, Implementation in an Existing, Enterprise-Specific Virtual Network for a New Deployment + +This use case seeks to align with the expectations of enterprise infrastructure.
+For instance, certain companies prohibit the use of public IP addresses in their solutions.
+The solution will provision certain elements such as Monitoring, Key Vault, permissions, and analytics services.
+However, additional configurations may be required before and after deployment.
+Choosing this option allows you to tailor the infrastructure, but typically requires customized services from the cloud, security, and network teams, leading to less agility and project delays.
+This case presents a balance between an extended deployment timeline and compliance with corporate policies and infrastructure requirements.
+ +Complexity could be notably high on the Virtual Network side.
+Anticipate the need for virtual network peering arrangements using a hub and spoke design, route tables, configuration of DNS, private zones, (sometimes) private endpoints, DNS forwarding for private links, virtual network delegations, and so on.
+Additionally, various analytics services may each have distinct virtual network requirements. + +This use case does not require any public IP addresses to be exposed.
+All services can utilize private Enterprise Network access exclusively. + +The identity of the solution administrator or the managing group must be submitted to gain access and control over the solution. + + +##### Virtual Network + +The enterprise network team needs to set up a virtual network with necessary components and settings in advance. This must be a spoke-type network connected to the central hub network with central Enterprise Firewall and connectivity to enterprise network - following the hub and spoke architecture. + +The Customer/Network team must set up a unique virtual network without overlapping the corporate address space, designate the right-sized subnets, manage network delegations, route tables, set up corporate DNS at the Virtual Network level, enroll private links in enterprise-grade private DNS zones with forwarding for resolving private links, and create specific Network Security Groups with tailored rules for certain services enabled in the solution. + +Creating at least a /26 subnet is essential for hosting private endpoints. As additional analytical services are activated, there will generally be a need for a greater number of subnets of varying sizes. +The services within the solution vary in their requirements. For instance, consider the needs of Azure Databricks: + +- https://learn.microsoft.com/en-us/azure/databricks/security/network/classic/vnet-inject#network-security-group-rules-for-workspaces +- https://learn.microsoft.com/en-us/azure/databricks/security/network/classic/udr + +Review the necessary subnets, subnet sizing, routing, DNS settings, network security groups, delegations for 'Microsoft.Databricks/workspaces', and private endpoints. + +If only full private access is required, the ```advancedOptions.networkAcls.ipRules``` parameter should not be configured. + +When utilizing a pre-defined virtual network provided by the Enterprise Network team (this use case), the ```virtualNetworkResourceId``` parameter should be set to reference the existing Virtual Network. + +##### Monitoring of the Solution + +The rules outlined here: [Monitoring of the Solution for Use Case 1](#monitoring-uc1) apply to this use case as well. + + +##### Storing Secrets - Key Vault + +If the parameter ```keyVaultResourceId``` is left unspecified or set to ```null```, a new Azure Key Vault will be created as part of the solution.
+Additional creation configurations for the Azure Key Vault are available under the parameter ```advancedOptions.keyVault.*```.
+ +This use case resembles use case [Storing Secrets - Key Vault for Use Case 1](#kv-uc1). +The difference is that the customer usually needs full private access in own virtual network and must configure (sometimes) private endpoints for the created Azure Key Vault. +This includes registering DNS records pointing to the private IP address under the private endpoint for Network Interface Card. +Additionally, the customer must create or use an existing Azure Key Vault private DNS zone to support private endpoint resolution +and integrate it with enterprise DNS and DNS forwarding mechanisms. + +To allow both private and public access, you can set the ```advancedOptions.networkAcls.ipRules``` parameter +to include the client's public IP (enables public endpoints for some services). + +For the handling of secrets, users need to have privileged roles. +Those listed in the ```solutionAdministrators.*``` parameter will receive 'Key Vault Administrator' +privileges specifically for Azure Key Vaults that are newly created.
+ +##### Solution Administrators + +The rules outlined here: [Solution Administrators for Use Case 1](#sol-admin-uc1) apply to this use case as well. + + +##### Analytical Service - Azure Databricks + +If the parameter ```enableDatabricks``` is set to ```true```, a new Azure Databricks instance will be created as part of the solution.
+Additional creation configurations for the Azure Databricks are available under the parameter ```advancedOptions.databricks.*```.
+ +This use case resembles use case [Analytical Service - Azure Databricks for Use Case 1](#adb-uc1). +The difference is that the customer usually needs full private access in own virtual network and must configure (sometimes) private endpoints for the created Azure Databricks. +This includes registering DNS records pointing to the private IP address under the private endpoint for Network Interface Card. +Additionally, the customer must create or use an existing Azure Databricks private DNS zone to support private endpoint resolution +and integrate it with enterprise DNS and DNS forwarding mechanisms. + +This use case usually involves integrating with a private virtual network. Refer to: [Virtual Network for Use Case 2](#vnet-uc2). +The network team needs to set up the virtual network to include a private links subnet and two additional subnets delegated for Azure Databricks. +Then, create (sometimes) two private endpoints, network security groups, and an Azure Databricks Zone. + +Refer to this guide for more information: +and this:
+ +To allow both private and public access, you can set the ```advancedOptions.networkAcls.ipRules``` parameter +to include the client's public IP (enables public endpoints for some services). +If you allow public access, additional manual setup is required to restrict public access for different clients. +Refer to this guide for more information:
+ +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'UC2' + params: { + // Required parameters + name: 'pawuc2' + // Non-required parameters + virtualNetworkResourceId: '/subscriptions/{SUBSCRIPTION-ID}/resourceGroups/{NAME-OF-RG}/providers/Microsoft.Network/virtualNetworks/{NAME-OF-VNET}' + logAnalyticsWorkspaceResourceId: null // null means new Log Analytical Workspace will be created + keyVaultResourceId: null // null means new Azure key Vault will be created + enableDatabricks: true // Part of the solution will be new instance of the Azure Databricks + solutionAdministrators: [ + { + principalId: // Specified group will have enough permissions to manage the solution + principalType: 'Group' // Group and/or User type can be specified + } + ] + advancedOptions: { + networkAcls: { ipRules: [] } // Which public IP addresses of the end users can access the solution (enables public endpoints for some services) + } + tags: { Owner: 'Contoso', 'Cost Center': '2345-324' } + } +} +``` + +#### Use Case 3: Integration with existing core Infrastructure + +This use case aims to meet the specific needs of enterprise infrastructure, similar to use case +[Use Case 2: Brownfield, Implementation in an Existing, Enterprise-Specific Virtual Network for a New Deployment](#uc2) but more advanced.
+It integrates with a pre-provisioned virtual network for private traffic and pre-provisioned Azure Key Vault and central Azure Log Analytics workspace.
+This allows the cloud and network teams to provide core components, and the solution linking them together.
+ +Cloud and network teams remain responsible for configuring prerequisites and providing elements like private endpoints (sometimes), private endpoint zones, DNS resolution, and access permissions.
+Find further information here: [Use Case 2: Brownfield, Implementation in an Existing, Enterprise-Specific Virtual Network for a New Deployment](#uc2)
+ +This use case does not require any public IP addresses to be exposed, +but you can enable public access with the ```advancedOptions.networkAcls.ipRules``` parameter if necessary.
+All services can utilize private Enterprise Network access exclusively. + +##### Virtual Network + +The rules outlined here: [Virtual Network for Use Case 2](#vnet-uc2) apply to this use case as well. + +##### Monitoring of the Solution + +The rules outlined here: [Monitoring of the Solution for Use Case 1](#monitoring-uc1) apply to this use case as well. + +The ```logAnalyticsWorkspaceResourceId``` parameter should be set to use an existing Azure Log Analytics Workspace.
+ +The team responsible for resource management must set up Azure Log Analytics Workspace access for the necessary end users.
+ +##### Storing Secrets - Key Vault + +The rules outlined here: [Storing Secrets - Key Vault for Use Case 2](#kv-uc2) apply to this use case as well. + +The ```keyVaultResourceId``` parameter should be set to use an existing Azure Key Vault.
+ +The team responsible for resource management must set up Azure Key Vault access for the necessary end users.
+ +##### Solution Administrators + +The rules outlined here: [Solution Administrators for Use Case 1](#sol-admin-uc1) apply to this use case as well.
+However, role assignments will apply exclusively to resources generated within this use case, excluding those pre-created by the network and cloud team.
+ +##### Analytical Service - Azure Databricks + +The rules outlined here: [Analytical Service - Azure Databricks for Use Case 2](#adb-uc2) apply to this use case as well. + +```bicep +module privateAnalyticalWorkspace 'br/public:avm/ptn/data/private-analytical-workspace:' = { + name: 'UC3' + params: { + // Required parameters + name: 'pawuc3' + // Non-required parameters + virtualNetworkResourceId: '/subscriptions/{SUBSCRIPTION-ID}/resourceGroups/{NAME-OF-RG}/providers/Microsoft.Network/virtualNetworks/{NAME-OF-VNET}' + logAnalyticsWorkspaceResourceId: '/subscriptions/{SUBSCRIPTION-ID}/resourceGroups/{NAME-OF-RG}/providers/Microsoft.OperationalInsights/workspaces/{NAME-OF-LOG}' + keyVaultResourceId: '/subscriptions/{SUBSCRIPTION-ID}/resourceGroups/{NAME-OF-RG}/providers/Microsoft.KeyVault/vaults/{NAME-OF-KV}' + enableDatabricks: true // Part of the solution will be new instance of the Azure Databricks + solutionAdministrators: [ + { + principalId: // Specified group will have enough permissions to manage the solution + principalType: 'Group' // Group and/or User type can be specified + } + ] + advancedOptions: { + networkAcls: { ipRules: [] } // Which public IP addresses of the end users can access the solution (enables public endpoints for some services) + } + tags: { Owner: 'Contoso', 'Cost Center': '2345-324' } + } +} +``` + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/ptn/data/private-analytical-workspace/main.bicep b/avm/ptn/data/private-analytical-workspace/main.bicep new file mode 100644 index 0000000000..a5cf9954a5 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/main.bicep @@ -0,0 +1,882 @@ +metadata name = 'private-analytical-workspace' +metadata description = 'This pattern module enables you to use Azure services that are typical for data analytics solutions. The goal is to help data scientists establish an environment for data analysis simply. It is secure by default for enterprise use. Data scientists should not spend much time on how to build infrastructure solution. They should mainly concentrate on the data analytics components they require for the solution.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the private analytical workspace solution and its components. Used to ensure unique resource names.') +param name string + +@description('Optional. Location for all Resources in the solution.') +param location string = resourceGroup().location + +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' +@description('Optional. The lock settings for all Resources in the solution.') +param lock lockType? + +@description('Optional. Tags for all Resources in the solution.') +param tags object? + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@description('Optional. Enable/Disable Azure Databricks service within the solution.') +param enableDatabricks bool = false + +@description('Optional. This option allows the solution to be connected to a VNET that the customer provides. If you have an existing VNET that was made for this solution, you can specify it here. If you do not use this option, this module will make a new VNET for you.') +param virtualNetworkResourceId string? + +@description('Optional. If you already have a Log Analytics Workspace that you want to use with the solution, you can specify it here. Otherwise, this module will create a new Log Analytics Workspace for you.') +param logAnalyticsWorkspaceResourceId string? + +@description('Optional. If you already have a Key Vault that you want to use with the solution, you can specify it here. Otherwise, this module will create a new Key Vault for you.') +param keyVaultResourceId string? + +@description('Optional. Array of users or groups who are in charge of the solution.') +param solutionAdministrators userGroupRoleAssignmentType[]? + +@description('Optional. Additional options that can affect some components of the solution and how they are configured.') +param advancedOptions advancedOptionsType? + +// ============== // +// Variables // +// ============== // + +var diagnosticSettingsName = 'avm-diagnostic-settings' + +var vnetName = '${name}-vnet' +var vnetDefaultAddressPrefix = '192.168.224.0/19' +var subnetPrivateLinkDefaultAddressPrefix = cidrSubnet(vnetDefaultAddressPrefix, 24, 0) // 192.168.224.0/24 +// DBW - 192.168.228.0/22 +var subnetDbwFrontendDefaultAddressPrefix = cidrSubnet(vnetDefaultAddressPrefix, 23, 2) // 192.168.228.0/23 +var subnetDbwBackendDefaultAddressPrefix = cidrSubnet(vnetDefaultAddressPrefix, 23, 3) // 192.168.230.0/23 + +var privateDnsZoneNameSaBlob = 'privatelink.blob.${environment().suffixes.storage}' +var privateDnsZoneNameKv = 'privatelink.vaultcore.azure.net' +var privateDnsZoneNameDbw = 'privatelink.azuredatabricks.net' +var subnetNamePrivateLink = 'private-link-subnet' +var subnetNameDbwFrontend = 'dbw-frontend-subnet' +var subnetNameDbwBackend = 'dbw-backend-subnet' +var nsgNamePrivateLink = '${name}-nsg-private-link' +var nsgRulesPrivateLink = [ + { + name: 'PrivateLinkDenyAllOutbound' + properties: { + description: 'Private Link subnet should not initiate any Outbound Connections' + access: 'Deny' + direction: 'Outbound' + priority: 100 + protocol: '*' + sourceAddressPrefix: '*' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRange: '*' + } + } +] +var nsgNameDbwFrontend = '${name}-nsg-dbw-frontend' +var nsgNameDbwBackend = '${name}-nsg-dbw-backend' +var nsgRulesDbw = [ + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-inbound' + properties: { + description: 'Required for worker nodes communication within a cluster' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-webapp' + properties: { + description: 'Required for workers communication with Databricks Webapp' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'AzureDatabricks' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-sql' + properties: { + description: 'Required for workers communication with Azure SQL services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '3306' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Sql' + access: 'Allow' + priority: 101 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-storage' + properties: { + description: 'Required for workers communication with Azure Storage services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Storage' + access: 'Allow' + priority: 102 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-outbound' + properties: { + description: 'Required for worker nodes communication within a cluster.' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 103 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-eventhub' + properties: { + description: 'Required for worker communication with Azure Eventhub services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '9093' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'EventHub' + access: 'Allow' + priority: 104 + direction: 'Outbound' + } + } + { + name: 'deny-hop-outbound' + properties: { + description: 'Subnet should not initiate any management Outbound Connections' + priority: 200 + access: 'Deny' + protocol: 'Tcp' + direction: 'Outbound' + sourceAddressPrefix: 'VirtualNetwork' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRanges: [ + '3389' + '22' + ] + } + } +] + +var logName = '${name}-log' +var logDefaultDailyQuotaGb = -1 +var logDefaultDataRetention = 365 + +var kvName = '${name}-kv' +var kvDefaultCreateMode = 'default' +var kvDefaultEnableSoftDelete = true +var kvDefaultSoftDeleteRetentionInDays = 90 +var kvDefaultEnablePurgeProtection = true +var kvDefaultSku = 'premium' + +var dbwName = '${name}-dbw' +var dbwAccessConnectorName = '${name}-dbw-acc' + +var createNewVNET = empty(virtualNetworkResourceId) +var createNewLog = empty(logAnalyticsWorkspaceResourceId) +var createNewKV = empty(keyVaultResourceId) + +var ownerRoleAssignments = [ + for (item, i) in empty(solutionAdministrators) ? [] : solutionAdministrators!: { + roleDefinitionIdOrName: 'Owner' + principalId: item.principalId + principalType: item.principalType + description: 'Full access to manage this resource, including the ability to assign roles in Azure RBAC.' + } +] + +var vnetCfg = ({ + resourceId: createNewVNET ? vnet.outputs.resourceId : vnetExisting.id + name: createNewVNET ? vnet.outputs.name : vnetExisting.name + location: createNewVNET ? vnet.outputs.location : vnetExisting.location + resourceGroupName: createNewVNET ? vnet.outputs.resourceGroupName : split(vnetExisting.id, '/')[4] + + subnetResourceIdPrivateLink: createNewVNET + ? vnet.outputs.subnetResourceIds[0] // private link subnet should be always available at zero index + : vnetExisting::subnetPrivateLink.id + subnetNameDbwFrontend: createNewVNET ? subnetNameDbwFrontend : vnetExisting::subnetDbwFrontend.name + subnetNameDbwBackend: createNewVNET ? subnetNameDbwBackend : vnetExisting::subnetDbwBackend.name +}) + +var logCfg = ({ + resourceId: createNewLog ? log.outputs.resourceId : logExisting.id + name: createNewLog ? log.outputs.name : logExisting.name + location: createNewLog ? log.outputs.location : logExisting.location + resourceGroupName: createNewLog ? log.outputs.resourceGroupName : split(logExisting.id, '/')[4] +}) + +var kvCfg = ({ + resourceId: createNewKV ? kv.outputs.resourceId : kvExisting.id + name: createNewKV ? kv.outputs.name : kvExisting.name + location: createNewKV ? kv.outputs.location : kvExisting.location + resourceGroupName: createNewKV ? kv.outputs.resourceGroupName : split(kvExisting.id, '/')[4] +}) + +var kvIpRules = [ + for (item, i) in empty(advancedOptions.?networkAcls.?ipRules) ? [] : advancedOptions!.networkAcls!.ipRules!: { + value: item + } +] + +var kvRoleAssignments = [ + for (item, i) in empty(solutionAdministrators) ? [] : solutionAdministrators!: { + roleDefinitionIdOrName: 'Key Vault Administrator' + principalId: item.principalId + principalType: item.principalType + description: 'Perform all data plane operations on a key vault and all objects in it, including certificates, keys, and secrets.' + } +] + +var kvMultipleRoleAssignments = concat(ownerRoleAssignments, kvRoleAssignments) + +var dbwIpRules = [ + for (item, i) in empty(advancedOptions.?networkAcls.?ipRules) ? [] : advancedOptions!.networkAcls!.ipRules!: { + value: item + } +] + +var privateLinkSubnet = [ + { + name: subnetNamePrivateLink + addressPrefix: subnetPrivateLinkDefaultAddressPrefix + networkSecurityGroupResourceId: nsgPrivateLink.outputs.resourceId + } +] + +var subnets = concat( + privateLinkSubnet, + // Subnets for service typically in the /22 chunk + enableDatabricks + ? [ + { + // a host subnet (sometimes called the public subnet) + name: subnetNameDbwFrontend + addressPrefix: subnetDbwFrontendDefaultAddressPrefix + networkSecurityGroupResourceId: nsgDbwFrontend.outputs.resourceId + delegation: 'Microsoft.Databricks/workspaces' + } + { + // a container subnet (sometimes called the private subnet) + name: subnetNameDbwBackend + addressPrefix: subnetDbwBackendDefaultAddressPrefix + networkSecurityGroupResourceId: nsgDbwBackend.outputs.resourceId + delegation: 'Microsoft.Databricks/workspaces' + } + ] + : [] +) + +// ============== // +// Resources // +// ============== // + +#disable-next-line no-deployments-resources +resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { + name: take( + '46d3xbcp.ptn.data-privateanalyticalworkspace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}', + 64 + ) + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +// +// Add your resources here +// + +resource vnetExisting 'Microsoft.Network/virtualNetworks@2023-11-01' existing = if (!createNewVNET) { + name: createNewVNET ? 'dummyName' : last(split(virtualNetworkResourceId!, '/')) + scope: resourceGroup( + createNewVNET ? subscription().id : (split(virtualNetworkResourceId!, '/')[2]), + createNewVNET ? resourceGroup().id : (split(virtualNetworkResourceId!, '/')[4]) + ) + + resource subnetPrivateLink 'subnets@2023-11-01' existing = if (!empty(advancedOptions.?virtualNetwork.?subnetNamePrivateLink)) { + name: advancedOptions.?virtualNetwork.?subnetNamePrivateLink ?? 'dummyName' + } + + resource subnetDbwFrontend 'subnets@2023-11-01' existing = if (enableDatabricks && !empty(advancedOptions.?databricks.?subnetNameFrontend)) { + name: advancedOptions.?databricks.?subnetNameFrontend ?? 'dummyName' + } + + resource subnetDbwBackend 'subnets@2023-11-01' existing = if (enableDatabricks && !empty(advancedOptions.?databricks.?subnetNameBackend)) { + name: advancedOptions.?databricks.?subnetNameBackend ?? 'dummyName' + } +} + +resource logExisting 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = if (!createNewLog) { + name: createNewLog ? 'dummyName' : last(split(logAnalyticsWorkspaceResourceId!, '/')) + scope: resourceGroup( + createNewLog ? subscription().id : (split(logAnalyticsWorkspaceResourceId!, '/')[2]), + createNewLog ? resourceGroup().id : (split(logAnalyticsWorkspaceResourceId!, '/')[4]) + ) +} + +resource kvExisting 'Microsoft.KeyVault/vaults@2023-07-01' existing = if (!createNewKV) { + name: createNewKV ? 'dummyName' : last(split(keyVaultResourceId!, '/')) + scope: resourceGroup( + createNewKV ? subscription().id : (split(keyVaultResourceId!, '/')[2]), + createNewKV ? resourceGroup().id : (split(keyVaultResourceId!, '/')[4]) + ) +} + +module vnet 'br/public:avm/res/network/virtual-network:0.5.0' = if (createNewVNET) { + name: '${uniqueString(deployment().name, location)}-vnet-${vnetName}' + params: { + // Required parameters + addressPrefixes: [ + vnetDefaultAddressPrefix + ] + name: vnetName + // Non-required parameters + diagnosticSettings: [ + { + name: diagnosticSettingsName + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + metricCategories: [ + { + category: 'AllMetrics' + } + ] + workspaceResourceId: logCfg.resourceId + } + ] + dnsServers: [] + enableTelemetry: enableTelemetry + location: location + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + lock: lock + subnets: subnets + tags: tags + } +} + +module nsgPrivateLink 'br/public:avm/res/network/network-security-group:0.5.0' = if (createNewVNET) { + name: '${uniqueString(deployment().name, location)}-nsg-${nsgNamePrivateLink}' + params: { + // Required parameters + name: nsgNamePrivateLink + // Non-required parameters + diagnosticSettings: [ + { + name: diagnosticSettingsName + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + workspaceResourceId: logCfg.resourceId + } + ] + enableTelemetry: enableTelemetry + location: location + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + lock: lock + tags: tags + securityRules: nsgRulesPrivateLink + } +} + +module nsgDbwFrontend 'br/public:avm/res/network/network-security-group:0.5.0' = if (createNewVNET && enableDatabricks) { + name: '${uniqueString(deployment().name, location)}-nsg-${nsgNameDbwFrontend}' + params: { + // Required parameters + name: nsgNameDbwFrontend + // Non-required parameters + diagnosticSettings: [ + { + name: diagnosticSettingsName + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + workspaceResourceId: logCfg.resourceId + } + ] + enableTelemetry: enableTelemetry + location: location + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + lock: lock + tags: tags + securityRules: nsgRulesDbw + } +} + +module nsgDbwBackend 'br/public:avm/res/network/network-security-group:0.5.0' = if (createNewVNET && enableDatabricks) { + name: '${uniqueString(deployment().name, location)}-nsg-${nsgNameDbwBackend}' + params: { + // Required parameters + name: nsgNameDbwBackend + // Non-required parameters + diagnosticSettings: [ + { + name: diagnosticSettingsName + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + workspaceResourceId: logCfg.resourceId + } + ] + enableTelemetry: enableTelemetry + location: location + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + lock: lock + tags: tags + securityRules: nsgRulesDbw + } +} + +module dnsZoneSaBlob 'br/public:avm/res/network/private-dns-zone:0.5.0' = if (createNewVNET && enableDatabricks) { + name: '${uniqueString(deployment().name, location)}-zone-${privateDnsZoneNameSaBlob}' + params: { + // Required parameters + name: privateDnsZoneNameSaBlob + // Non-required parameters + enableTelemetry: enableTelemetry + location: 'global' + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + lock: lock + tags: tags + virtualNetworkLinks: [ + { + registrationEnabled: false + virtualNetworkResourceId: vnet.outputs.resourceId + } + ] + } +} + +module log 'br/public:avm/res/operational-insights/workspace:0.7.1' = if (createNewLog) { + name: '${uniqueString(deployment().name, location)}-law-${logName}' + params: { + // Required parameters + name: logName + // Non-required parameters + dailyQuotaGb: advancedOptions.?logAnalyticsWorkspace.?dailyQuotaGb ?? logDefaultDailyQuotaGb + dataRetention: advancedOptions.?logAnalyticsWorkspace.?dataRetention ?? logDefaultDataRetention + diagnosticSettings: [] + enableTelemetry: enableTelemetry + location: location + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + lock: lock + skuName: 'PerGB2018' + tags: tags + } +} + +module kv 'br/public:avm/res/key-vault/vault:0.9.0' = if (createNewKV) { + name: '${uniqueString(deployment().name, location)}-vault-${kvName}' + params: { + // Required parameters + name: kvName + // Non-required parameters + createMode: advancedOptions.?keyVault.?createMode ?? kvDefaultCreateMode + diagnosticSettings: [ + { + name: diagnosticSettingsName + metricCategories: [ + { + category: 'AllMetrics' + } + ] + logCategoriesAndGroups: [ + { + categoryGroup: 'audit' + } + { + categoryGroup: 'allLogs' + } + ] + workspaceResourceId: logCfg.resourceId + } + ] + enablePurgeProtection: advancedOptions.?keyVault.?enablePurgeProtection ?? kvDefaultEnablePurgeProtection + enableRbacAuthorization: true + enableSoftDelete: advancedOptions.?keyVault.?enableSoftDelete ?? kvDefaultEnableSoftDelete + enableTelemetry: enableTelemetry + enableVaultForDeployment: false + enableVaultForTemplateDeployment: false + enableVaultForDiskEncryption: false // When enabledForDiskEncryption is true, networkAcls.bypass must include 'AzureServices' + location: location + lock: lock + networkAcls: { + bypass: 'None' + defaultAction: 'Deny' + ipRules: kvIpRules + } + privateEndpoints: [ + // Private endpoint for Key Vault only for new VNET + { + name: '${name}-kv-pep' + location: location + subnetResourceId: vnetCfg.subnetResourceIdPrivateLink + privateDnsZoneGroup: createNewVNET + ? { + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: dnsZoneKv.outputs.resourceId + } + ] + } + : null + tags: tags + enableTelemetry: enableTelemetry + lock: lock + roleAssignments: empty(ownerRoleAssignments) ? [] : ownerRoleAssignments + } + ] + publicNetworkAccess: empty(kvIpRules) ? 'Disabled' : 'Enabled' + roleAssignments: empty(kvMultipleRoleAssignments) ? [] : kvMultipleRoleAssignments + sku: advancedOptions.?keyVault.?sku == 'standard' ? 'standard' : kvDefaultSku + softDeleteRetentionInDays: advancedOptions.?keyVault.?softDeleteRetentionInDays ?? kvDefaultSoftDeleteRetentionInDays + tags: tags + } +} + +module dnsZoneKv 'br/public:avm/res/network/private-dns-zone:0.6.0' = if (createNewVNET && createNewKV) { + name: '${uniqueString(deployment().name, location)}-zone-${privateDnsZoneNameKv}' + params: { + // Required parameters + name: privateDnsZoneNameKv + // Non-required parameters + enableTelemetry: enableTelemetry + location: 'global' + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + lock: lock + tags: tags + virtualNetworkLinks: [ + { + registrationEnabled: false + virtualNetworkResourceId: vnet.outputs.resourceId + } + ] + } +} + +module accessConnector 'br/public:avm/res/databricks/access-connector:0.3.0' = if (enableDatabricks) { + name: '${uniqueString(deployment().name, location)}-connector-${dbwAccessConnectorName}' + params: { + // Required parameters + name: dbwAccessConnectorName + // Non-required parameters + enableTelemetry: enableTelemetry + location: location + lock: lock + managedIdentities: { + systemAssigned: true + } + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + tags: tags + } +} + +module dbw 'br/public:avm/res/databricks/workspace:0.8.5' = if (enableDatabricks) { + name: '${uniqueString(deployment().name, location)}-workspace-${dbwName}' + params: { + // Required parameters + name: dbwName + // Conditional parameters + accessConnectorResourceId: accessConnector.outputs.resourceId + // Non-required parameters + customPublicSubnetName: createNewVNET ? subnetNameDbwFrontend : advancedOptions.?databricks.?subnetNameFrontend + customPrivateSubnetName: createNewVNET ? subnetNameDbwBackend : advancedOptions.?databricks.?subnetNameBackend + customVirtualNetworkResourceId: vnetCfg.resourceId + diagnosticSettings: [ + { + name: diagnosticSettingsName + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + workspaceResourceId: logCfg.resourceId + } + ] + // With secure cluster connectivity enabled, customer virtual networks have no open ports and Databricks Runtime cluster nodes have no public IP addresses. + disablePublicIp: true // true means Secure Cluster Connectivity is enabled + enableTelemetry: enableTelemetry + location: location + lock: lock + managedResourceGroupResourceId: null // Maybe in the future we can support custom RG + prepareEncryption: true + privateEndpoints: [ + { + name: '${name}-dbw-ui-pep' + location: location + service: 'databricks_ui_api' + subnetResourceId: vnetCfg.subnetResourceIdPrivateLink + privateDnsZoneGroup: createNewVNET + ? { + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: dnsZoneDbw.outputs.resourceId + } + ] + } + : null + tags: tags + enableTelemetry: enableTelemetry + lock: lock + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + } + { + name: '${name}-dbw-auth-pep' + location: location + service: 'browser_authentication' + subnetResourceId: vnetCfg.subnetResourceIdPrivateLink + privateDnsZoneGroup: createNewVNET + ? { + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: dnsZoneDbw.outputs.resourceId + } + ] + } + : null + tags: tags + enableTelemetry: enableTelemetry + lock: lock + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + } + ] + privateStorageAccount: 'Enabled' + // Allow Public Network Access + // Enabled means You can connect to your Databricks workspace either publicly, via the public IP addresses, or privately, using a private endpoint. + publicNetworkAccess: empty(dbwIpRules) ? 'Disabled' : 'Enabled' + // Select No Azure Databricks Rules if you are using back-end Private Link, + // which means that your workspace data plane does not need network security group rules + // to connect to the Azure Databricks control plane. Otherwise, select All Rules. + requiredNsgRules: empty(dbwIpRules) ? 'NoAzureDatabricksRules' : 'AllRules' // In some environments with 'NoAzureDatabricksRules' cluster cannot be created + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + skuName: 'premium' // We need premium to use VNET injection, Private Connectivity (Requires Premium Plan) + storageAccountName: null // TODO add existing one (maybe with PEP) - https://learn.microsoft.com/en-us/azure/databricks/security/network/storage/firewall-support + storageAccountPrivateEndpoints: [ + { + name: '${name}-sa-blob-pep' + location: location + service: 'blob' + subnetResourceId: vnetCfg.subnetResourceIdPrivateLink + privateDnsZoneGroup: createNewVNET + ? { + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: dnsZoneSaBlob.outputs.resourceId + } + ] + } + : null + tags: tags + enableTelemetry: enableTelemetry + lock: lock + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + } + ] + tags: tags + } +} + +module dnsZoneDbw 'br/public:avm/res/network/private-dns-zone:0.6.0' = if (createNewVNET && enableDatabricks) { + name: '${uniqueString(deployment().name, location)}-zone-${privateDnsZoneNameDbw}' + params: { + // Required parameters + name: privateDnsZoneNameDbw + // Non-required parameters + enableTelemetry: enableTelemetry + location: 'global' + roleAssignments: !empty(ownerRoleAssignments) ? ownerRoleAssignments : [] + lock: lock + tags: tags + virtualNetworkLinks: [ + { + registrationEnabled: false + virtualNetworkResourceId: vnet.outputs.resourceId + } + ] + } +} + +// ============ // +// Outputs // +// ============ // + +@description('The resource ID of the resource.') +output resourceId string = vnetCfg.resourceId + +@description('The name of the resource.') +output name string = vnetCfg.name + +@description('The location the resource was deployed into.') +output location string = vnetCfg.location + +@description('The name of the managed resource group.') +output resourceGroupName string = vnetCfg.resourceGroupName + +@description('The resource ID of the Azure Virtual Network.') +output virtualNetworkResourceId string = vnetCfg.resourceId + +@description('The name of the Azure Virtual Network.') +output virtualNetworkName string = vnetCfg.name + +@description('The location of the Azure Virtual Network.') +output virtualNetworkLocation string = vnetCfg.location + +@description('The name of the Azure Virtual Network resource group.') +output virtualNetworkResourceGroupName string = vnetCfg.resourceGroupName + +@description('The resource ID of the Azure Log Analytics Workspace.') +output logAnalyticsWorkspaceResourceId string = logCfg.resourceId + +@description('The name of the Azure Log Analytics Workspace.') +output logAnalyticsWorkspaceName string = logCfg.name + +@description('The location of the Azure Log Analytics Workspace.') +output logAnalyticsWorkspaceLocation string = logCfg.location + +@description('The name of the Azure Log Analytics Workspace resource group.') +output logAnalyticsWorkspaceResourceGroupName string = logCfg.resourceGroupName + +@description('The resource ID of the Azure Key Vault.') +output keyVaultResourceId string = kvCfg.resourceId + +@description('The name of the Azure Key Vault.') +output keyVaultName string = kvCfg.name + +@description('The location of the Azure Key Vault.') +output keyVaultLocation string = kvCfg.location + +@description('The name of the Azure Key Vault resource group.') +output keyVaultResourceGroupName string = kvCfg.resourceGroupName + +@description('Conditional. The resource ID of the Azure Databricks when `enableDatabricks` is `true`.') +output databricksResourceId string = enableDatabricks ? dbw.outputs.resourceId : '' + +@description('Conditional. The name of the Azure Databricks when `enableDatabricks` is `true`.') +output databricksName string = enableDatabricks ? dbw.outputs.name : '' + +@description('Conditional. The location of the Azure Databricks when `enableDatabricks` is `true`.') +output databricksLocation string = enableDatabricks ? dbw.outputs.location : '' + +@description('Conditional. The name of the Azure Databricks resource group when `enableDatabricks` is `true`.') +output databricksResourceGroupName string = enableDatabricks ? dbw.outputs.resourceGroupName : '' + +// ================ // +// Definitions // +// ================ // + +@export() +type userGroupRoleAssignmentType = { + @description('Required. The principal ID of the principal (user/group) to assign the role to.') + principalId: string + + @description('Required. The principal type of the assigned principal ID.') + principalType: ('Group' | 'User') +} + +@export() +type networkAclsType = { + @description('Optional. Sets the public IP addresses or ranges that are allowed to access resources in the solution.') + ipRules: string[]? +} + +@export() +type virtualNetworkType = { + @description('Optional. The name of the existing Private Link Subnet within the Virtual Network in the parameter: \'virtualNetworkResourceId\'.') + subnetNamePrivateLink: string? +} + +@export() +type logAnalyticsWorkspaceType = { + @description('Optional. Number of days data will be retained for. The default value is: \'365\'.') + @minValue(0) + @maxValue(730) + dataRetention: int? + + @description('Optional. The workspace daily quota for ingestion. The default value is: \'-1\' (not limited).') + @minValue(-1) + dailyQuotaGb: int? +} + +@export() +type keyVaultType = { + @description('Optional. The vault\'s create mode to indicate whether the vault need to be recovered or not. The default value is: \'default\'.') + createMode: ('default' | 'recover')? + + @description('Optional. Specifies the SKU for the vault. The default value is: \'premium\'.') + sku: ('standard' | 'premium')? + + @description('Optional. Switch to enable/disable Key Vault\'s soft delete feature. The default value is: \'true\'.') + enableSoftDelete: bool? + + @description('Optional. Soft delete data retention days. It accepts >=7 and <=90. The default value is: \'90\'.') + softDeleteRetentionInDays: int? + + @description('Optional. Provide \'true\' to enable Key Vault\'s purge protection feature. The default value is: \'true\'.') + enablePurgeProtection: bool? +} + +@export() +type databricksType = { + // must be providied when DBW is going to be enabled and VNET is provided + @description('Optional. The name of the existing frontend Subnet for Azure Databricks within the Virtual Network in the parameter: \'virtualNetworkResourceId\'.') + subnetNameFrontend: string? + + @description('Optional. The name of the existing backend Subnet for Azure Databricks within the Virtual Network in the parameter: \'virtualNetworkResourceId\'.') + subnetNameBackend: string? +} + +@export() +type advancedOptionsType = { + @description('Optional. You can use this parameter to integrate the solution with an existing Azure Virtual Network if the \'virtualNetworkResourceId\' parameter is not empty.') + virtualNetwork: virtualNetworkType? + + @description('Optional. Networks Access Control Lists. This value has public IP addresses or ranges that are allowed to access resources in the solution.') + networkAcls: networkAclsType? + + @description('Optional. This parameter allows you to specify additional settings for Azure Log Analytics Workspace if the \'logAnalyticsWorkspaceResourceId\' parameter is empty.') + logAnalyticsWorkspace: logAnalyticsWorkspaceType? + + @description('Optional. This parameter allows you to specify additional settings for Azure Key Vault if the \'keyVaultResourceId\' parameter is empty.') + keyVault: keyVaultType? + + @description('Optional. This parameter allows you to specify additional settings for Azure Databricks if you set the \'enableDatabricks\' parameter to \'true\'.') + databricks: databricksType? +} diff --git a/avm/ptn/data/private-analytical-workspace/main.json b/avm/ptn/data/private-analytical-workspace/main.json new file mode 100644 index 0000000000..78d6897ac2 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/main.json @@ -0,0 +1,21629 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "4437449109602171238" + }, + "name": "private-analytical-workspace", + "description": "This pattern module enables you to use Azure services that are typical for data analytics solutions. The goal is to help data scientists establish an environment for data analysis simply. It is secure by default for enterprise use. Data scientists should not spend much time on how to build infrastructure solution. They should mainly concentrate on the data analytics components they require for the solution.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "userGroupRoleAssignmentType": { + "type": "object", + "properties": { + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Group", + "User" + ], + "metadata": { + "description": "Required. The principal type of the assigned principal ID." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "networkAclsType": { + "type": "object", + "properties": { + "ipRules": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Sets the public IP addresses or ranges that are allowed to access resources in the solution." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "virtualNetworkType": { + "type": "object", + "properties": { + "subnetNamePrivateLink": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the existing Private Link Subnet within the Virtual Network in the parameter: 'virtualNetworkResourceId'." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "logAnalyticsWorkspaceType": { + "type": "object", + "properties": { + "dataRetention": { + "type": "int", + "nullable": true, + "minValue": 0, + "maxValue": 730, + "metadata": { + "description": "Optional. Number of days data will be retained for. The default value is: '365'." + } + }, + "dailyQuotaGb": { + "type": "int", + "nullable": true, + "minValue": -1, + "metadata": { + "description": "Optional. The workspace daily quota for ingestion. The default value is: '-1' (not limited)." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "keyVaultType": { + "type": "object", + "properties": { + "createMode": { + "type": "string", + "allowedValues": [ + "default", + "recover" + ], + "nullable": true, + "metadata": { + "description": "Optional. The vault's create mode to indicate whether the vault need to be recovered or not. The default value is: 'default'." + } + }, + "sku": { + "type": "string", + "allowedValues": [ + "premium", + "standard" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the SKU for the vault. The default value is: 'premium'." + } + }, + "enableSoftDelete": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Switch to enable/disable Key Vault's soft delete feature. The default value is: 'true'." + } + }, + "softDeleteRetentionInDays": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Soft delete data retention days. It accepts >=7 and <=90. The default value is: '90'." + } + }, + "enablePurgeProtection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Provide 'true' to enable Key Vault's purge protection feature. The default value is: 'true'." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "databricksType": { + "type": "object", + "properties": { + "subnetNameFrontend": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the existing frontend Subnet for Azure Databricks within the Virtual Network in the parameter: 'virtualNetworkResourceId'." + } + }, + "subnetNameBackend": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the existing backend Subnet for Azure Databricks within the Virtual Network in the parameter: 'virtualNetworkResourceId'." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "advancedOptionsType": { + "type": "object", + "properties": { + "virtualNetwork": { + "$ref": "#/definitions/virtualNetworkType", + "nullable": true, + "metadata": { + "description": "Optional. You can use this parameter to integrate the solution with an existing Azure Virtual Network if the 'virtualNetworkResourceId' parameter is not empty." + } + }, + "networkAcls": { + "$ref": "#/definitions/networkAclsType", + "nullable": true, + "metadata": { + "description": "Optional. Networks Access Control Lists. This value has public IP addresses or ranges that are allowed to access resources in the solution." + } + }, + "logAnalyticsWorkspace": { + "$ref": "#/definitions/logAnalyticsWorkspaceType", + "nullable": true, + "metadata": { + "description": "Optional. This parameter allows you to specify additional settings for Azure Log Analytics Workspace if the 'logAnalyticsWorkspaceResourceId' parameter is empty." + } + }, + "keyVault": { + "$ref": "#/definitions/keyVaultType", + "nullable": true, + "metadata": { + "description": "Optional. This parameter allows you to specify additional settings for Azure Key Vault if the 'keyVaultResourceId' parameter is empty." + } + }, + "databricks": { + "$ref": "#/definitions/databricksType", + "nullable": true, + "metadata": { + "description": "Optional. This parameter allows you to specify additional settings for Azure Databricks if you set the 'enableDatabricks' parameter to 'true'." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private analytical workspace solution and its components. Used to ensure unique resource names." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources in the solution." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. The lock settings for all Resources in the solution." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all Resources in the solution." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "enableDatabricks": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enable/Disable Azure Databricks service within the solution." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. This option allows the solution to be connected to a VNET that the customer provides. If you have an existing VNET that was made for this solution, you can specify it here. If you do not use this option, this module will make a new VNET for you." + } + }, + "logAnalyticsWorkspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. If you already have a Log Analytics Workspace that you want to use with the solution, you can specify it here. Otherwise, this module will create a new Log Analytics Workspace for you." + } + }, + "keyVaultResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. If you already have a Key Vault that you want to use with the solution, you can specify it here. Otherwise, this module will create a new Key Vault for you." + } + }, + "solutionAdministrators": { + "type": "array", + "items": { + "$ref": "#/definitions/userGroupRoleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of users or groups who are in charge of the solution." + } + }, + "advancedOptions": { + "$ref": "#/definitions/advancedOptionsType", + "nullable": true, + "metadata": { + "description": "Optional. Additional options that can affect some components of the solution and how they are configured." + } + } + }, + "variables": { + "copy": [ + { + "name": "ownerRoleAssignments", + "count": "[length(if(empty(parameters('solutionAdministrators')), createArray(), parameters('solutionAdministrators')))]", + "input": { + "roleDefinitionIdOrName": "Owner", + "principalId": "[if(empty(parameters('solutionAdministrators')), createArray(), parameters('solutionAdministrators'))[copyIndex('ownerRoleAssignments')].principalId]", + "principalType": "[if(empty(parameters('solutionAdministrators')), createArray(), parameters('solutionAdministrators'))[copyIndex('ownerRoleAssignments')].principalType]", + "description": "Full access to manage this resource, including the ability to assign roles in Azure RBAC." + } + }, + { + "name": "kvIpRules", + "count": "[length(if(empty(tryGet(tryGet(parameters('advancedOptions'), 'networkAcls'), 'ipRules')), createArray(), parameters('advancedOptions').networkAcls.ipRules))]", + "input": { + "value": "[if(empty(tryGet(tryGet(parameters('advancedOptions'), 'networkAcls'), 'ipRules')), createArray(), parameters('advancedOptions').networkAcls.ipRules)[copyIndex('kvIpRules')]]" + } + }, + { + "name": "kvRoleAssignments", + "count": "[length(if(empty(parameters('solutionAdministrators')), createArray(), parameters('solutionAdministrators')))]", + "input": { + "roleDefinitionIdOrName": "Key Vault Administrator", + "principalId": "[if(empty(parameters('solutionAdministrators')), createArray(), parameters('solutionAdministrators'))[copyIndex('kvRoleAssignments')].principalId]", + "principalType": "[if(empty(parameters('solutionAdministrators')), createArray(), parameters('solutionAdministrators'))[copyIndex('kvRoleAssignments')].principalType]", + "description": "Perform all data plane operations on a key vault and all objects in it, including certificates, keys, and secrets." + } + }, + { + "name": "dbwIpRules", + "count": "[length(if(empty(tryGet(tryGet(parameters('advancedOptions'), 'networkAcls'), 'ipRules')), createArray(), parameters('advancedOptions').networkAcls.ipRules))]", + "input": { + "value": "[if(empty(tryGet(tryGet(parameters('advancedOptions'), 'networkAcls'), 'ipRules')), createArray(), parameters('advancedOptions').networkAcls.ipRules)[copyIndex('dbwIpRules')]]" + } + } + ], + "diagnosticSettingsName": "avm-diagnostic-settings", + "vnetName": "[format('{0}-vnet', parameters('name'))]", + "vnetDefaultAddressPrefix": "192.168.224.0/19", + "subnetPrivateLinkDefaultAddressPrefix": "[cidrSubnet(variables('vnetDefaultAddressPrefix'), 24, 0)]", + "subnetDbwFrontendDefaultAddressPrefix": "[cidrSubnet(variables('vnetDefaultAddressPrefix'), 23, 2)]", + "subnetDbwBackendDefaultAddressPrefix": "[cidrSubnet(variables('vnetDefaultAddressPrefix'), 23, 3)]", + "privateDnsZoneNameSaBlob": "[format('privatelink.blob.{0}', environment().suffixes.storage)]", + "privateDnsZoneNameKv": "privatelink.vaultcore.azure.net", + "privateDnsZoneNameDbw": "privatelink.azuredatabricks.net", + "subnetNamePrivateLink": "private-link-subnet", + "subnetNameDbwFrontend": "dbw-frontend-subnet", + "subnetNameDbwBackend": "dbw-backend-subnet", + "nsgNamePrivateLink": "[format('{0}-nsg-private-link', parameters('name'))]", + "nsgRulesPrivateLink": [ + { + "name": "PrivateLinkDenyAllOutbound", + "properties": { + "description": "Private Link subnet should not initiate any Outbound Connections", + "access": "Deny", + "direction": "Outbound", + "priority": 100, + "protocol": "*", + "sourceAddressPrefix": "*", + "sourcePortRange": "*", + "destinationAddressPrefix": "*", + "destinationPortRange": "*" + } + } + ], + "nsgNameDbwFrontend": "[format('{0}-nsg-dbw-frontend', parameters('name'))]", + "nsgNameDbwBackend": "[format('{0}-nsg-dbw-backend', parameters('name'))]", + "nsgRulesDbw": [ + { + "name": "Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-inbound", + "properties": { + "description": "Required for worker nodes communication within a cluster", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 100, + "direction": "Inbound" + } + }, + { + "name": "Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-webapp", + "properties": { + "description": "Required for workers communication with Databricks Webapp", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "443", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "AzureDatabricks", + "access": "Allow", + "priority": 100, + "direction": "Outbound" + } + }, + { + "name": "Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-sql", + "properties": { + "description": "Required for workers communication with Azure SQL services.", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3306", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "Sql", + "access": "Allow", + "priority": 101, + "direction": "Outbound" + } + }, + { + "name": "Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-storage", + "properties": { + "description": "Required for workers communication with Azure Storage services.", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "443", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "Storage", + "access": "Allow", + "priority": 102, + "direction": "Outbound" + } + }, + { + "name": "Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-outbound", + "properties": { + "description": "Required for worker nodes communication within a cluster.", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 103, + "direction": "Outbound" + } + }, + { + "name": "Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-eventhub", + "properties": { + "description": "Required for worker communication with Azure Eventhub services.", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "9093", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "EventHub", + "access": "Allow", + "priority": 104, + "direction": "Outbound" + } + }, + { + "name": "deny-hop-outbound", + "properties": { + "description": "Subnet should not initiate any management Outbound Connections", + "priority": 200, + "access": "Deny", + "protocol": "Tcp", + "direction": "Outbound", + "sourceAddressPrefix": "VirtualNetwork", + "sourcePortRange": "*", + "destinationAddressPrefix": "*", + "destinationPortRanges": [ + "3389", + "22" + ] + } + } + ], + "logName": "[format('{0}-log', parameters('name'))]", + "logDefaultDailyQuotaGb": -1, + "logDefaultDataRetention": 365, + "kvName": "[format('{0}-kv', parameters('name'))]", + "kvDefaultCreateMode": "default", + "kvDefaultEnableSoftDelete": true, + "kvDefaultSoftDeleteRetentionInDays": 90, + "kvDefaultEnablePurgeProtection": true, + "kvDefaultSku": "premium", + "dbwName": "[format('{0}-dbw', parameters('name'))]", + "dbwAccessConnectorName": "[format('{0}-dbw-acc', parameters('name'))]", + "createNewVNET": "[empty(parameters('virtualNetworkResourceId'))]", + "createNewLog": "[empty(parameters('logAnalyticsWorkspaceResourceId'))]", + "createNewKV": "[empty(parameters('keyVaultResourceId'))]", + "kvMultipleRoleAssignments": "[concat(variables('ownerRoleAssignments'), variables('kvRoleAssignments'))]" + }, + "resources": { + "vnetExisting::subnetPrivateLink": { + "condition": "[and(not(variables('createNewVNET')), not(empty(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'))))]", + "existing": true, + "type": "Microsoft.Network/virtualNetworks/subnets", + "apiVersion": "2023-11-01", + "subscriptionId": "[if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2])]", + "resourceGroup": "[if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])]", + "name": "[format('{0}/{1}', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))]", + "dependsOn": [ + "vnetExisting" + ] + }, + "vnetExisting::subnetDbwFrontend": { + "condition": "[and(not(variables('createNewVNET')), and(parameters('enableDatabricks'), not(empty(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend')))))]", + "existing": true, + "type": "Microsoft.Network/virtualNetworks/subnets", + "apiVersion": "2023-11-01", + "subscriptionId": "[if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2])]", + "resourceGroup": "[if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])]", + "name": "[format('{0}/{1}', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName'))]", + "dependsOn": [ + "vnetExisting" + ] + }, + "vnetExisting::subnetDbwBackend": { + "condition": "[and(not(variables('createNewVNET')), and(parameters('enableDatabricks'), not(empty(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend')))))]", + "existing": true, + "type": "Microsoft.Network/virtualNetworks/subnets", + "apiVersion": "2023-11-01", + "subscriptionId": "[if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2])]", + "resourceGroup": "[if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])]", + "name": "[format('{0}/{1}', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))]", + "dependsOn": [ + "vnetExisting" + ] + }, + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[take(format('46d3xbcp.ptn.data-privateanalyticalworkspace.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4)), 64)]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "vnetExisting": { + "condition": "[not(variables('createNewVNET'))]", + "existing": true, + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2023-11-01", + "subscriptionId": "[if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2])]", + "resourceGroup": "[if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])]", + "name": "[if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))]" + }, + "logExisting": { + "condition": "[not(variables('createNewLog'))]", + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "subscriptionId": "[if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2])]", + "resourceGroup": "[if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])]", + "name": "[if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))]" + }, + "kvExisting": { + "condition": "[not(variables('createNewKV'))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2023-07-01", + "subscriptionId": "[if(variables('createNewKV'), subscription().id, split(parameters('keyVaultResourceId'), '/')[2])]", + "resourceGroup": "[if(variables('createNewKV'), resourceGroup().id, split(parameters('keyVaultResourceId'), '/')[4])]", + "name": "[if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/')))]" + }, + "vnet": { + "condition": "[variables('createNewVNET')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-vnet-{1}', uniqueString(deployment().name, parameters('location')), variables('vnetName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "addressPrefixes": { + "value": [ + "[variables('vnetDefaultAddressPrefix')]" + ] + }, + "name": { + "value": "[variables('vnetName')]" + }, + "diagnosticSettings": { + "value": [ + { + "name": "[variables('diagnosticSettingsName')]", + "logCategoriesAndGroups": [ + { + "categoryGroup": "allLogs" + } + ], + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "workspaceResourceId": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).resourceId]" + } + ] + }, + "dnsServers": { + "value": [] + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "lock": { + "value": "[parameters('lock')]" + }, + "subnets": { + "value": "[concat(createArray(createObject('name', variables('subnetNamePrivateLink'), 'addressPrefix', variables('subnetPrivateLinkDefaultAddressPrefix'), 'networkSecurityGroupResourceId', reference('nsgPrivateLink').outputs.resourceId.value)), if(parameters('enableDatabricks'), createArray(createObject('name', variables('subnetNameDbwFrontend'), 'addressPrefix', variables('subnetDbwFrontendDefaultAddressPrefix'), 'networkSecurityGroupResourceId', reference('nsgDbwFrontend').outputs.resourceId.value, 'delegation', 'Microsoft.Databricks/workspaces'), createObject('name', variables('subnetNameDbwBackend'), 'addressPrefix', variables('subnetDbwBackendDefaultAddressPrefix'), 'networkSecurityGroupResourceId', reference('nsgDbwBackend').outputs.resourceId.value, 'delegation', 'Microsoft.Databricks/workspaces')), createArray()))]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "12023193036665775110" + }, + "name": "Virtual Networks", + "description": "This module deploys a Virtual Network (vNet).", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "peeringType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Name of VNET Peering resource. If not provided, default value will be peer-localVnetName-remoteVnetName." + } + }, + "remoteVirtualNetworkResourceId": { + "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", + "nullable": 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", + "nullable": true, + "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", + "nullable": 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", + "nullable": true, + "metadata": { + "description": "Optional. Do not verify the provisioning state of the remote gateway. Default is true." + } + }, + "useRemoteGateways": { + "type": "bool", + "nullable": true, + "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." + } + }, + "remotePeeringEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Deploy the outbound and the inbound peering." + } + }, + "remotePeeringName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the VNET Peering resource in the remove Virtual Network. If not provided, default value will be peer-remoteVnetName-localVnetName." + } + }, + "remotePeeringAllowForwardedTraffic": { + "type": "bool", + "nullable": 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." + } + }, + "remotePeeringAllowGatewayTransit": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false." + } + }, + "remotePeeringAllowVirtualNetworkAccess": { + "type": "bool", + "nullable": 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." + } + }, + "remotePeeringDoNotVerifyRemoteGateways": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Do not verify the provisioning state of the remote gateway. Default is true." + } + }, + "remotePeeringUseRemoteGateways": { + "type": "bool", + "nullable": true, + "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." + } + } + } + }, + "subnetType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The Name of the subnet resource." + } + }, + "addressPrefix": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty." + } + }, + "addressPrefixes": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty." + } + }, + "applicationGatewayIPConfigurations": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application gateway IP configurations of virtual network resource." + } + }, + "delegation": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The delegation to enable on the subnet." + } + }, + "natGatewayResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the NAT Gateway to use for the subnet." + } + }, + "networkSecurityGroupResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the network security group to assign to the subnet." + } + }, + "privateEndpointNetworkPolicies": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled", + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. enable or disable apply network policies on private endpoint in the subnet." + } + }, + "privateLinkServiceNetworkPolicies": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. enable or disable apply network policies on private link service in the subnet." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "routeTableResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the route table to assign to the subnet." + } + }, + "serviceEndpointPolicies": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. An array of service endpoint policies." + } + }, + "serviceEndpoints": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The service endpoints to enable on the subnet." + } + }, + "defaultOutboundAccess": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Set this property to false to disable default outbound connectivity for all VMs in the subnet. This property can only be set at the time of subnet creation and cannot be updated for an existing subnet." + } + }, + "sharingScope": { + "type": "string", + "allowedValues": [ + "DelegatedServices", + "Tenant" + ], + "nullable": true, + "metadata": { + "description": "Optional. Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty." + } + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Virtual Network (vNet)." + } + }, + "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." + } + }, + "virtualNetworkBgpCommunity": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The BGP community associated with the virtual network." + } + }, + "subnets": { + "type": "array", + "items": { + "$ref": "#/definitions/subnetType" + }, + "nullable": true, + "metadata": { + "description": "Optional. An Array of subnets to deploy to the Virtual Network." + } + }, + "dnsServers": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. DNS Servers associated to the Virtual Network." + } + }, + "ddosProtectionPlanResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "peerings": { + "type": "array", + "items": { + "$ref": "#/definitions/peeringType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Virtual Network Peering configurations." + } + }, + "vnetEncryption": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates if encryption is enabled on virtual network and if VM without encryption is allowed in encrypted VNet. Requires the EnableVNetEncryption feature to be registered for the subscription and a supported region to use this property." + } + }, + "vnetEncryptionEnforcement": { + "type": "string", + "defaultValue": "AllowUnencrypted", + "allowedValues": [ + "AllowUnencrypted", + "DropUnencrypted" + ], + "metadata": { + "description": "Optional. If the encrypted VNet allows VM that does not support encryption. Can only be used when vnetEncryption is enabled." + } + }, + "flowTimeoutInMinutes": { + "type": "int", + "defaultValue": 0, + "maxValue": 30, + "metadata": { + "description": "Optional. The flow timeout in minutes for the Virtual Network, which is used to enable connection tracking for intra-VM flows. Possible values are between 4 and 30 minutes. Default value 0 will set the property to null." + } + }, + "diagnosticSettings": { + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "enableVmProtection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicates if VM protection is enabled for all the subnets in the virtual network." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-virtualnetwork.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "virtualNetwork": { + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2024-01-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "addressSpace": { + "addressPrefixes": "[parameters('addressPrefixes')]" + }, + "bgpCommunities": "[if(not(empty(parameters('virtualNetworkBgpCommunity'))), createObject('virtualNetworkCommunity', parameters('virtualNetworkBgpCommunity')), null())]", + "ddosProtectionPlan": "[if(not(empty(parameters('ddosProtectionPlanResourceId'))), createObject('id', parameters('ddosProtectionPlanResourceId')), null())]", + "dhcpOptions": "[if(not(empty(parameters('dnsServers'))), createObject('dnsServers', array(parameters('dnsServers'))), null())]", + "enableDdosProtection": "[not(empty(parameters('ddosProtectionPlanResourceId')))]", + "encryption": "[if(equals(parameters('vnetEncryption'), true()), createObject('enabled', parameters('vnetEncryption'), 'enforcement', parameters('vnetEncryptionEnforcement')), null())]", + "flowTimeoutInMinutes": "[if(not(equals(parameters('flowTimeoutInMinutes'), 0)), parameters('flowTimeoutInMinutes'), null())]", + "enableVmProtection": "[parameters('enableVmProtection')]" + } + }, + "virtualNetwork_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "virtualNetwork" + ] + }, + "virtualNetwork_diagnosticSettings": { + "copy": { + "name": "virtualNetwork_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "metrics", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics'))))]", + "input": { + "category": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')].category]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')], 'enabled'), true())]", + "timeGrain": null + } + }, + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "virtualNetwork" + ] + }, + "virtualNetwork_roleAssignments": { + "copy": { + "name": "virtualNetwork_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/virtualNetworks', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "virtualNetwork" + ] + }, + "virtualNetwork_subnets": { + "copy": { + "name": "virtualNetwork_subnets", + "count": "[length(coalesce(parameters('subnets'), createArray()))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-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": "[coalesce(parameters('subnets'), createArray())[copyIndex()].name]" + }, + "addressPrefix": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'addressPrefix')]" + }, + "addressPrefixes": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'addressPrefixes')]" + }, + "applicationGatewayIPConfigurations": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'applicationGatewayIPConfigurations')]" + }, + "delegation": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'delegation')]" + }, + "natGatewayResourceId": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'natGatewayResourceId')]" + }, + "networkSecurityGroupResourceId": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'networkSecurityGroupResourceId')]" + }, + "privateEndpointNetworkPolicies": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'privateEndpointNetworkPolicies')]" + }, + "privateLinkServiceNetworkPolicies": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'privateLinkServiceNetworkPolicies')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "routeTableResourceId": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'routeTableResourceId')]" + }, + "serviceEndpointPolicies": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'serviceEndpointPolicies')]" + }, + "serviceEndpoints": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'serviceEndpoints')]" + }, + "defaultOutboundAccess": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'defaultOutboundAccess')]" + }, + "sharingScope": { + "value": "[tryGet(coalesce(parameters('subnets'), createArray())[copyIndex()], 'sharingScope')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "6411714881793832751" + }, + "name": "Virtual Network Subnets", + "description": "This module deploys a Virtual Network Subnet.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Requird. The Name of the subnet resource." + } + }, + "virtualNetworkName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual network. Required if the template is used in a standalone deployment." + } + }, + "addressPrefix": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty." + } + }, + "networkSecurityGroupResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the network security group to assign to the subnet." + } + }, + "routeTableResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the route table to assign to the subnet." + } + }, + "serviceEndpoints": { + "type": "array", + "items": { + "type": "string" + }, + "defaultValue": [], + "metadata": { + "description": "Optional. The service endpoints to enable on the subnet." + } + }, + "delegation": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The delegation to enable on the subnet." + } + }, + "natGatewayResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the NAT Gateway to use for the subnet." + } + }, + "privateEndpointNetworkPolicies": { + "type": "string", + "nullable": true, + "allowedValues": [ + "Disabled", + "Enabled", + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" + ], + "metadata": { + "description": "Optional. Enable or disable apply network policies on private endpoint in the subnet." + } + }, + "privateLinkServiceNetworkPolicies": { + "type": "string", + "nullable": true, + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. Enable or disable apply network policies on private link service in the subnet." + } + }, + "addressPrefixes": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty." + } + }, + "defaultOutboundAccess": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Set this property to false to disable default outbound connectivity for all VMs in the subnet. This property can only be set at the time of subnet creation and cannot be updated for an existing subnet." + } + }, + "sharingScope": { + "type": "string", + "allowedValues": [ + "DelegatedServices", + "Tenant" + ], + "nullable": true, + "metadata": { + "description": "Optional. Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty." + } + }, + "applicationGatewayIPConfigurations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Application gateway IP configurations of virtual network resource." + } + }, + "serviceEndpointPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of service endpoint policies." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "virtualNetwork": { + "existing": true, + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2024-01-01", + "name": "[parameters('virtualNetworkName')]" + }, + "subnet": { + "type": "Microsoft.Network/virtualNetworks/subnets", + "apiVersion": "2024-01-01", + "name": "[format('{0}/{1}', parameters('virtualNetworkName'), parameters('name'))]", + "properties": { + "copy": [ + { + "name": "serviceEndpoints", + "count": "[length(parameters('serviceEndpoints'))]", + "input": { + "service": "[parameters('serviceEndpoints')[copyIndex('serviceEndpoints')]]" + } + } + ], + "addressPrefix": "[parameters('addressPrefix')]", + "addressPrefixes": "[parameters('addressPrefixes')]", + "networkSecurityGroup": "[if(not(empty(parameters('networkSecurityGroupResourceId'))), createObject('id', parameters('networkSecurityGroupResourceId')), null())]", + "routeTable": "[if(not(empty(parameters('routeTableResourceId'))), createObject('id', parameters('routeTableResourceId')), null())]", + "natGateway": "[if(not(empty(parameters('natGatewayResourceId'))), createObject('id', parameters('natGatewayResourceId')), null())]", + "delegations": "[if(not(empty(parameters('delegation'))), createArray(createObject('name', parameters('delegation'), 'properties', createObject('serviceName', parameters('delegation')))), createArray())]", + "privateEndpointNetworkPolicies": "[parameters('privateEndpointNetworkPolicies')]", + "privateLinkServiceNetworkPolicies": "[parameters('privateLinkServiceNetworkPolicies')]", + "applicationGatewayIPConfigurations": "[parameters('applicationGatewayIPConfigurations')]", + "serviceEndpointPolicies": "[parameters('serviceEndpointPolicies')]", + "defaultOutboundAccess": "[parameters('defaultOutboundAccess')]", + "sharingScope": "[parameters('sharingScope')]" + }, + "dependsOn": [ + "virtualNetwork" + ] + }, + "subnet_roleAssignments": { + "copy": { + "name": "subnet_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}/subnets/{1}', parameters('virtualNetworkName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "subnet" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the virtual network peering was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the virtual network peering." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the virtual network peering." + }, + "value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name'))]" + }, + "addressPrefix": { + "type": "string", + "metadata": { + "description": "The address prefix for the subnet." + }, + "value": "[coalesce(tryGet(reference('subnet'), 'addressPrefix'), '')]" + }, + "addressPrefixes": { + "type": "array", + "metadata": { + "description": "List of address prefixes for the subnet." + }, + "value": "[coalesce(tryGet(reference('subnet'), 'addressPrefixes'), createArray())]" + } + } + } + }, + "dependsOn": [ + "virtualNetwork" + ] + }, + "virtualNetwork_peering_local": { + "copy": { + "name": "virtualNetwork_peering_local", + "count": "[length(coalesce(parameters('peerings'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-virtualNetworkPeering-local-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "localVnetName": { + "value": "[parameters('name')]" + }, + "remoteVirtualNetworkResourceId": { + "value": "[coalesce(parameters('peerings'), createArray())[copyIndex()].remoteVirtualNetworkResourceId]" + }, + "name": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'name')]" + }, + "allowForwardedTraffic": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'allowForwardedTraffic')]" + }, + "allowGatewayTransit": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'allowGatewayTransit')]" + }, + "allowVirtualNetworkAccess": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'allowVirtualNetworkAccess')]" + }, + "doNotVerifyRemoteGateways": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'doNotVerifyRemoteGateways')]" + }, + "useRemoteGateways": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'useRemoteGateways')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "345394220621166229" + }, + "name": "Virtual Network Peerings", + "description": "This module deploys a Virtual Network Peering.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[format('peer-{0}-{1}', parameters('localVnetName'), last(split(parameters('remoteVirtualNetworkResourceId'), '/')))]", + "metadata": { + "description": "Optional. The Name of VNET Peering resource. If not provided, default value will be localVnetName-remoteVnetName." + } + }, + "localVnetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Virtual Network to add the peering to. Required if the template is used in a standalone deployment." + } + }, + "remoteVirtualNetworkResourceId": { + "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." + } + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings", + "apiVersion": "2024-01-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('remoteVirtualNetworkResourceId')]" + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the virtual network peering was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the virtual network peering." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the virtual network peering." + }, + "value": "[resourceId('Microsoft.Network/virtualNetworks/virtualNetworkPeerings', parameters('localVnetName'), parameters('name'))]" + } + } + } + }, + "dependsOn": [ + "virtualNetwork", + "virtualNetwork_subnets" + ] + }, + "virtualNetwork_peering_remote": { + "copy": { + "name": "virtualNetwork_peering_remote", + "count": "[length(coalesce(parameters('peerings'), createArray()))]" + }, + "condition": "[coalesce(tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'remotePeeringEnabled'), false())]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-virtualNetworkPeering-remote-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "subscriptionId": "[split(coalesce(parameters('peerings'), createArray())[copyIndex()].remoteVirtualNetworkResourceId, '/')[2]]", + "resourceGroup": "[split(coalesce(parameters('peerings'), createArray())[copyIndex()].remoteVirtualNetworkResourceId, '/')[4]]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "localVnetName": { + "value": "[last(split(coalesce(parameters('peerings'), createArray())[copyIndex()].remoteVirtualNetworkResourceId, '/'))]" + }, + "remoteVirtualNetworkResourceId": { + "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + }, + "name": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'remotePeeringName')]" + }, + "allowForwardedTraffic": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'remotePeeringAllowForwardedTraffic')]" + }, + "allowGatewayTransit": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'remotePeeringAllowGatewayTransit')]" + }, + "allowVirtualNetworkAccess": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'remotePeeringAllowVirtualNetworkAccess')]" + }, + "doNotVerifyRemoteGateways": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'remotePeeringDoNotVerifyRemoteGateways')]" + }, + "useRemoteGateways": { + "value": "[tryGet(coalesce(parameters('peerings'), createArray())[copyIndex()], 'remotePeeringUseRemoteGateways')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "345394220621166229" + }, + "name": "Virtual Network Peerings", + "description": "This module deploys a Virtual Network Peering.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[format('peer-{0}-{1}', parameters('localVnetName'), last(split(parameters('remoteVirtualNetworkResourceId'), '/')))]", + "metadata": { + "description": "Optional. The Name of VNET Peering resource. If not provided, default value will be localVnetName-remoteVnetName." + } + }, + "localVnetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Virtual Network to add the peering to. Required if the template is used in a standalone deployment." + } + }, + "remoteVirtualNetworkResourceId": { + "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." + } + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings", + "apiVersion": "2024-01-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('remoteVirtualNetworkResourceId')]" + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the virtual network peering was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the virtual network peering." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the virtual network peering." + }, + "value": "[resourceId('Microsoft.Network/virtualNetworks/virtualNetworkPeerings', parameters('localVnetName'), parameters('name'))]" + } + } + } + }, + "dependsOn": [ + "virtualNetwork", + "virtualNetwork_subnets" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the virtual network was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the virtual network." + }, + "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the virtual network." + }, + "value": "[parameters('name')]" + }, + "subnetNames": { + "type": "array", + "metadata": { + "description": "The names of the deployed subnets." + }, + "copy": { + "count": "[length(coalesce(parameters('subnets'), createArray()))]", + "input": "[reference(format('virtualNetwork_subnets[{0}]', copyIndex())).outputs.name.value]" + } + }, + "subnetResourceIds": { + "type": "array", + "metadata": { + "description": "The resource IDs of the deployed subnets." + }, + "copy": { + "count": "[length(coalesce(parameters('subnets'), createArray()))]", + "input": "[reference(format('virtualNetwork_subnets[{0}]', copyIndex())).outputs.resourceId.value]" + } + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('virtualNetwork', '2024-01-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "log", + "logExisting", + "nsgDbwBackend", + "nsgDbwFrontend", + "nsgPrivateLink" + ] + }, + "nsgPrivateLink": { + "condition": "[variables('createNewVNET')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-nsg-{1}', uniqueString(deployment().name, parameters('location')), variables('nsgNamePrivateLink'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('nsgNamePrivateLink')]" + }, + "diagnosticSettings": { + "value": [ + { + "name": "[variables('diagnosticSettingsName')]", + "logCategoriesAndGroups": [ + { + "categoryGroup": "allLogs" + } + ], + "workspaceResourceId": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).resourceId]" + } + ] + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "lock": { + "value": "[parameters('lock')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "securityRules": { + "value": "[variables('nsgRulesPrivateLink')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "32550557190395602" + }, + "name": "Network Security Groups", + "description": "This module deploys a Network security Group (NSG).", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "securityRulesType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the security rule." + } + }, + "properties": { + "type": "object", + "properties": { + "access": { + "type": "string", + "allowedValues": [ + "Allow", + "Deny" + ], + "metadata": { + "description": "Required. Whether network traffic is allowed or denied." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the security rule." + } + }, + "destinationAddressPrefix": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. 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", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The destination address prefixes. CIDR or destination IP ranges." + } + }, + "destinationApplicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource IDs of the application security groups specified as destination." + } + }, + "destinationPortRange": { + "type": "string", + "nullable": true, + "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", + "items": { + "type": "string" + }, + "nullable": true, + "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", + "minValue": 100, + "maxValue": 4096, + "metadata": { + "description": "Required. 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", + "nullable": true, + "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", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The CIDR or source IP ranges." + } + }, + "sourceApplicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource IDs of the application security groups specified as source." + } + }, + "sourcePortRange": { + "type": "string", + "nullable": true, + "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", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The source port ranges." + } + } + }, + "metadata": { + "description": "Required. The properties of the security rule." + } + } + } + }, + "nullable": true + } + }, + "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": { + "$ref": "#/definitions/securityRulesType", + "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." + } + }, + "flushConnection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When enabled, flows created from Network Security Group connections will be re-evaluated when rules are updates. Initial enablement will trigger re-evaluation. Network Security Group connection flushing is not available in all regions." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the NSG resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-networksecuritygroup.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "networkSecurityGroup": { + "type": "Microsoft.Network/networkSecurityGroups", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "securityRules", + "count": "[length(coalesce(parameters('securityRules'), createArray()))]", + "input": { + "name": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].name]", + "properties": { + "access": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.access]", + "description": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'description'), '')]", + "destinationAddressPrefix": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationAddressPrefix'), '')]", + "destinationAddressPrefixes": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationAddressPrefixes'), createArray())]", + "destinationApplicationSecurityGroups": "[map(coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationApplicationSecurityGroupResourceIds'), createArray()), lambda('destinationApplicationSecurityGroupResourceId', createObject('id', lambdaVariables('destinationApplicationSecurityGroupResourceId'))))]", + "destinationPortRange": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationPortRange'), '')]", + "destinationPortRanges": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationPortRanges'), createArray())]", + "direction": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.direction]", + "priority": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.priority]", + "protocol": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.protocol]", + "sourceAddressPrefix": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourceAddressPrefix'), '')]", + "sourceAddressPrefixes": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourceAddressPrefixes'), createArray())]", + "sourceApplicationSecurityGroups": "[map(coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourceApplicationSecurityGroupResourceIds'), createArray()), lambda('sourceApplicationSecurityGroupResourceId', createObject('id', lambdaVariables('sourceApplicationSecurityGroupResourceId'))))]", + "sourcePortRange": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourcePortRange'), '')]", + "sourcePortRanges": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourcePortRanges'), createArray())]" + } + } + } + ], + "flushConnection": "[parameters('flushConnection')]" + } + }, + "networkSecurityGroup_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "networkSecurityGroup" + ] + }, + "networkSecurityGroup_diagnosticSettings": { + "copy": { + "name": "networkSecurityGroup_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "networkSecurityGroup" + ] + }, + "networkSecurityGroup_roleAssignments": { + "copy": { + "name": "networkSecurityGroup_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/networkSecurityGroups', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "networkSecurityGroup" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the network security group was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the network security group." + }, + "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the network security group." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('networkSecurityGroup', '2023-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "log", + "logExisting" + ] + }, + "nsgDbwFrontend": { + "condition": "[and(variables('createNewVNET'), parameters('enableDatabricks'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-nsg-{1}', uniqueString(deployment().name, parameters('location')), variables('nsgNameDbwFrontend'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('nsgNameDbwFrontend')]" + }, + "diagnosticSettings": { + "value": [ + { + "name": "[variables('diagnosticSettingsName')]", + "logCategoriesAndGroups": [ + { + "categoryGroup": "allLogs" + } + ], + "workspaceResourceId": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).resourceId]" + } + ] + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "lock": { + "value": "[parameters('lock')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "securityRules": { + "value": "[variables('nsgRulesDbw')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "32550557190395602" + }, + "name": "Network Security Groups", + "description": "This module deploys a Network security Group (NSG).", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "securityRulesType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the security rule." + } + }, + "properties": { + "type": "object", + "properties": { + "access": { + "type": "string", + "allowedValues": [ + "Allow", + "Deny" + ], + "metadata": { + "description": "Required. Whether network traffic is allowed or denied." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the security rule." + } + }, + "destinationAddressPrefix": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. 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", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The destination address prefixes. CIDR or destination IP ranges." + } + }, + "destinationApplicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource IDs of the application security groups specified as destination." + } + }, + "destinationPortRange": { + "type": "string", + "nullable": true, + "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", + "items": { + "type": "string" + }, + "nullable": true, + "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", + "minValue": 100, + "maxValue": 4096, + "metadata": { + "description": "Required. 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", + "nullable": true, + "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", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The CIDR or source IP ranges." + } + }, + "sourceApplicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource IDs of the application security groups specified as source." + } + }, + "sourcePortRange": { + "type": "string", + "nullable": true, + "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", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The source port ranges." + } + } + }, + "metadata": { + "description": "Required. The properties of the security rule." + } + } + } + }, + "nullable": true + } + }, + "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": { + "$ref": "#/definitions/securityRulesType", + "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." + } + }, + "flushConnection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When enabled, flows created from Network Security Group connections will be re-evaluated when rules are updates. Initial enablement will trigger re-evaluation. Network Security Group connection flushing is not available in all regions." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the NSG resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-networksecuritygroup.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "networkSecurityGroup": { + "type": "Microsoft.Network/networkSecurityGroups", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "securityRules", + "count": "[length(coalesce(parameters('securityRules'), createArray()))]", + "input": { + "name": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].name]", + "properties": { + "access": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.access]", + "description": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'description'), '')]", + "destinationAddressPrefix": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationAddressPrefix'), '')]", + "destinationAddressPrefixes": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationAddressPrefixes'), createArray())]", + "destinationApplicationSecurityGroups": "[map(coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationApplicationSecurityGroupResourceIds'), createArray()), lambda('destinationApplicationSecurityGroupResourceId', createObject('id', lambdaVariables('destinationApplicationSecurityGroupResourceId'))))]", + "destinationPortRange": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationPortRange'), '')]", + "destinationPortRanges": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationPortRanges'), createArray())]", + "direction": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.direction]", + "priority": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.priority]", + "protocol": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.protocol]", + "sourceAddressPrefix": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourceAddressPrefix'), '')]", + "sourceAddressPrefixes": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourceAddressPrefixes'), createArray())]", + "sourceApplicationSecurityGroups": "[map(coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourceApplicationSecurityGroupResourceIds'), createArray()), lambda('sourceApplicationSecurityGroupResourceId', createObject('id', lambdaVariables('sourceApplicationSecurityGroupResourceId'))))]", + "sourcePortRange": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourcePortRange'), '')]", + "sourcePortRanges": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourcePortRanges'), createArray())]" + } + } + } + ], + "flushConnection": "[parameters('flushConnection')]" + } + }, + "networkSecurityGroup_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "networkSecurityGroup" + ] + }, + "networkSecurityGroup_diagnosticSettings": { + "copy": { + "name": "networkSecurityGroup_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "networkSecurityGroup" + ] + }, + "networkSecurityGroup_roleAssignments": { + "copy": { + "name": "networkSecurityGroup_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/networkSecurityGroups', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "networkSecurityGroup" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the network security group was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the network security group." + }, + "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the network security group." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('networkSecurityGroup', '2023-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "log", + "logExisting" + ] + }, + "nsgDbwBackend": { + "condition": "[and(variables('createNewVNET'), parameters('enableDatabricks'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-nsg-{1}', uniqueString(deployment().name, parameters('location')), variables('nsgNameDbwBackend'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('nsgNameDbwBackend')]" + }, + "diagnosticSettings": { + "value": [ + { + "name": "[variables('diagnosticSettingsName')]", + "logCategoriesAndGroups": [ + { + "categoryGroup": "allLogs" + } + ], + "workspaceResourceId": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).resourceId]" + } + ] + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "lock": { + "value": "[parameters('lock')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "securityRules": { + "value": "[variables('nsgRulesDbw')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "32550557190395602" + }, + "name": "Network Security Groups", + "description": "This module deploys a Network security Group (NSG).", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "securityRulesType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the security rule." + } + }, + "properties": { + "type": "object", + "properties": { + "access": { + "type": "string", + "allowedValues": [ + "Allow", + "Deny" + ], + "metadata": { + "description": "Required. Whether network traffic is allowed or denied." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the security rule." + } + }, + "destinationAddressPrefix": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. 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", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The destination address prefixes. CIDR or destination IP ranges." + } + }, + "destinationApplicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource IDs of the application security groups specified as destination." + } + }, + "destinationPortRange": { + "type": "string", + "nullable": true, + "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", + "items": { + "type": "string" + }, + "nullable": true, + "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", + "minValue": 100, + "maxValue": 4096, + "metadata": { + "description": "Required. 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", + "nullable": true, + "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", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The CIDR or source IP ranges." + } + }, + "sourceApplicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource IDs of the application security groups specified as source." + } + }, + "sourcePortRange": { + "type": "string", + "nullable": true, + "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", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The source port ranges." + } + } + }, + "metadata": { + "description": "Required. The properties of the security rule." + } + } + } + }, + "nullable": true + } + }, + "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": { + "$ref": "#/definitions/securityRulesType", + "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." + } + }, + "flushConnection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When enabled, flows created from Network Security Group connections will be re-evaluated when rules are updates. Initial enablement will trigger re-evaluation. Network Security Group connection flushing is not available in all regions." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the NSG resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-networksecuritygroup.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "networkSecurityGroup": { + "type": "Microsoft.Network/networkSecurityGroups", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "securityRules", + "count": "[length(coalesce(parameters('securityRules'), createArray()))]", + "input": { + "name": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].name]", + "properties": { + "access": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.access]", + "description": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'description'), '')]", + "destinationAddressPrefix": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationAddressPrefix'), '')]", + "destinationAddressPrefixes": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationAddressPrefixes'), createArray())]", + "destinationApplicationSecurityGroups": "[map(coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationApplicationSecurityGroupResourceIds'), createArray()), lambda('destinationApplicationSecurityGroupResourceId', createObject('id', lambdaVariables('destinationApplicationSecurityGroupResourceId'))))]", + "destinationPortRange": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationPortRange'), '')]", + "destinationPortRanges": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'destinationPortRanges'), createArray())]", + "direction": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.direction]", + "priority": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.priority]", + "protocol": "[coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties.protocol]", + "sourceAddressPrefix": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourceAddressPrefix'), '')]", + "sourceAddressPrefixes": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourceAddressPrefixes'), createArray())]", + "sourceApplicationSecurityGroups": "[map(coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourceApplicationSecurityGroupResourceIds'), createArray()), lambda('sourceApplicationSecurityGroupResourceId', createObject('id', lambdaVariables('sourceApplicationSecurityGroupResourceId'))))]", + "sourcePortRange": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourcePortRange'), '')]", + "sourcePortRanges": "[coalesce(tryGet(coalesce(parameters('securityRules'), createArray())[copyIndex('securityRules')].properties, 'sourcePortRanges'), createArray())]" + } + } + } + ], + "flushConnection": "[parameters('flushConnection')]" + } + }, + "networkSecurityGroup_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "networkSecurityGroup" + ] + }, + "networkSecurityGroup_diagnosticSettings": { + "copy": { + "name": "networkSecurityGroup_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "networkSecurityGroup" + ] + }, + "networkSecurityGroup_roleAssignments": { + "copy": { + "name": "networkSecurityGroup_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/networkSecurityGroups', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "networkSecurityGroup" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the network security group was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the network security group." + }, + "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the network security group." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('networkSecurityGroup', '2023-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "log", + "logExisting" + ] + }, + "dnsZoneSaBlob": { + "condition": "[and(variables('createNewVNET'), parameters('enableDatabricks'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-zone-{1}', uniqueString(deployment().name, parameters('location')), variables('privateDnsZoneNameSaBlob'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('privateDnsZoneNameSaBlob')]" + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "global" + }, + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "lock": { + "value": "[parameters('lock')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "virtualNetworkLinks": { + "value": [ + { + "registrationEnabled": false, + "virtualNetworkResourceId": "[reference('vnet').outputs.resourceId.value]" + } + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "17411368014038876941" + }, + "name": "Private DNS Zones", + "description": "This module deploys a Private DNS zone.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "aType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "aRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipv4Address": { + "type": "string", + "metadata": { + "description": "Required. The IPv4 address of this A record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of A records in the record set." + } + } + } + }, + "nullable": true + }, + "aaaaType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "aaaaRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipv6Address": { + "type": "string", + "metadata": { + "description": "Required. The IPv6 address of this AAAA record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of AAAA records in the record set." + } + } + } + }, + "nullable": true + }, + "cnameType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "cnameRecord": { + "type": "object", + "properties": { + "cname": { + "type": "string", + "metadata": { + "description": "Required. The canonical name of the CNAME record." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The CNAME record in the record set." + } + } + } + }, + "nullable": true + }, + "mxType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "mxRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "exchange": { + "type": "string", + "metadata": { + "description": "Required. The domain name of the mail host for this MX record." + } + }, + "preference": { + "type": "int", + "metadata": { + "description": "Required. The preference value for this MX record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of MX records in the record set." + } + } + } + }, + "nullable": true + }, + "ptrType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "ptrRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ptrdname": { + "type": "string", + "metadata": { + "description": "Required. The PTR target domain name for this PTR record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of PTR records in the record set." + } + } + } + }, + "nullable": true + }, + "soaType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "soaRecord": { + "type": "object", + "properties": { + "email": { + "type": "string", + "metadata": { + "description": "Required. The email contact for this SOA record." + } + }, + "expireTime": { + "type": "int", + "metadata": { + "description": "Required. The expire time for this SOA record." + } + }, + "host": { + "type": "string", + "metadata": { + "description": "Required. The domain name of the authoritative name server for this SOA record." + } + }, + "minimumTtl": { + "type": "int", + "metadata": { + "description": "Required. The minimum value for this SOA record. By convention this is used to determine the negative caching duration." + } + }, + "refreshTime": { + "type": "int", + "metadata": { + "description": "Required. The refresh value for this SOA record." + } + }, + "retryTime": { + "type": "int", + "metadata": { + "description": "Required. The retry time for this SOA record." + } + }, + "serialNumber": { + "type": "int", + "metadata": { + "description": "Required. The serial number for this SOA record." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The SOA record in the record set." + } + } + } + }, + "nullable": true + }, + "srvType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "srvRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "priority": { + "type": "int", + "metadata": { + "description": "Required. The priority value for this SRV record." + } + }, + "weight": { + "type": "int", + "metadata": { + "description": "Required. The weight value for this SRV record." + } + }, + "port": { + "type": "int", + "metadata": { + "description": "Required. The port value for this SRV record." + } + }, + "target": { + "type": "string", + "metadata": { + "description": "Required. The target domain name for this SRV record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of SRV records in the record set." + } + } + } + }, + "nullable": true + }, + "txtType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "txtRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The text value of this TXT record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of TXT records in the record set." + } + } + } + }, + "nullable": true + }, + "virtualNetworkLinkType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 80, + "metadata": { + "description": "Optional. The resource name." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the virtual network to link." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Azure Region where the resource lives." + } + }, + "registrationEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Private DNS zone name." + } + }, + "a": { + "$ref": "#/definitions/aType", + "metadata": { + "description": "Optional. Array of A records." + } + }, + "aaaa": { + "$ref": "#/definitions/aaaaType", + "metadata": { + "description": "Optional. Array of AAAA records." + } + }, + "cname": { + "$ref": "#/definitions/cnameType", + "metadata": { + "description": "Optional. Array of CNAME records." + } + }, + "mx": { + "$ref": "#/definitions/mxType", + "metadata": { + "description": "Optional. Array of MX records." + } + }, + "ptr": { + "$ref": "#/definitions/ptrType", + "metadata": { + "description": "Optional. Array of PTR records." + } + }, + "soa": { + "$ref": "#/definitions/soaType", + "metadata": { + "description": "Optional. Array of SOA records." + } + }, + "srv": { + "$ref": "#/definitions/srvType", + "metadata": { + "description": "Optional. Array of SRV records." + } + }, + "txt": { + "$ref": "#/definitions/txtType", + "metadata": { + "description": "Optional. Array of TXT records." + } + }, + "virtualNetworkLinks": { + "$ref": "#/definitions/virtualNetworkLinkType", + "metadata": { + "description": "Optional. Array of custom objects describing vNet links of the DNS zone. Each object should contain properties 'virtualNetworkResourceId' 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." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. The location of the PrivateDNSZone. Should be global." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privatednszone.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateDnsZone": { + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + "privateDnsZone_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_roleAssignments": { + "copy": { + "name": "privateDnsZone_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_A": { + "copy": { + "name": "privateDnsZone_A", + "count": "[length(coalesce(parameters('a'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-ARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('a'), createArray())[copyIndex()].name]" + }, + "aRecords": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'aRecords')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "11343565859504250241" + }, + "name": "Private DNS Zone A record", + "description": "This module deploys a Private DNS Zone A record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the A record." + } + }, + "aRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of A records in the record set." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "A": { + "type": "Microsoft.Network/privateDnsZones/A", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "aRecords": "[parameters('aRecords')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "A_roleAssignments": { + "copy": { + "name": "A_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/A/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "A" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed A record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed A record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed A record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_AAAA": { + "copy": { + "name": "privateDnsZone_AAAA", + "count": "[length(coalesce(parameters('aaaa'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-AAAARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('aaaa'), createArray())[copyIndex()].name]" + }, + "aaaaRecords": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'aaaaRecords')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "3700934406905797316" + }, + "name": "Private DNS Zone AAAA record", + "description": "This module deploys a Private DNS Zone AAAA record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the AAAA record." + } + }, + "aaaaRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of AAAA records in the record set." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "AAAA": { + "type": "Microsoft.Network/privateDnsZones/AAAA", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "aaaaRecords": "[parameters('aaaaRecords')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "AAAA_roleAssignments": { + "copy": { + "name": "AAAA_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/AAAA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "AAAA" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed AAAA record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed AAAA record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed AAAA record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_CNAME": { + "copy": { + "name": "privateDnsZone_CNAME", + "count": "[length(coalesce(parameters('cname'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-CNAMERecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('cname'), createArray())[copyIndex()].name]" + }, + "cnameRecord": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'cnameRecord')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "12929118683431932277" + }, + "name": "Private DNS Zone CNAME record", + "description": "This module deploys a Private DNS Zone CNAME record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the CNAME record." + } + }, + "cnameRecord": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. A CNAME record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "CNAME": { + "type": "Microsoft.Network/privateDnsZones/CNAME", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "cnameRecord": "[parameters('cnameRecord')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "CNAME_roleAssignments": { + "copy": { + "name": "CNAME_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/CNAME/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "CNAME" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed CNAME record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed CNAME record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed CNAME record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_MX": { + "copy": { + "name": "privateDnsZone_MX", + "count": "[length(coalesce(parameters('mx'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-MXRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('mx'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'metadata')]" + }, + "mxRecords": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'mxRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "14178508926823177155" + }, + "name": "Private DNS Zone MX record", + "description": "This module deploys a Private DNS Zone MX record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the MX record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "mxRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of MX records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "MX": { + "type": "Microsoft.Network/privateDnsZones/MX", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "mxRecords": "[parameters('mxRecords')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "MX_roleAssignments": { + "copy": { + "name": "MX_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/MX/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "MX" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed MX record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed MX record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed MX record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_PTR": { + "copy": { + "name": "privateDnsZone_PTR", + "count": "[length(coalesce(parameters('ptr'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-PTRRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('ptr'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'metadata')]" + }, + "ptrRecords": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'ptrRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "8082128465097964607" + }, + "name": "Private DNS Zone PTR record", + "description": "This module deploys a Private DNS Zone PTR record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the PTR record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ptrRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of PTR records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "PTR": { + "type": "Microsoft.Network/privateDnsZones/PTR", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "ptrRecords": "[parameters('ptrRecords')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "PTR_roleAssignments": { + "copy": { + "name": "PTR_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/PTR/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "PTR" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed PTR record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed PTR record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed PTR record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_SOA": { + "copy": { + "name": "privateDnsZone_SOA", + "count": "[length(coalesce(parameters('soa'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-SOARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('soa'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'metadata')]" + }, + "soaRecord": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'soaRecord')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "6755707328778392735" + }, + "name": "Private DNS Zone SOA record", + "description": "This module deploys a Private DNS Zone SOA record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SOA record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "soaRecord": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. A SOA record." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "SOA": { + "type": "Microsoft.Network/privateDnsZones/SOA", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "soaRecord": "[parameters('soaRecord')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "SOA_roleAssignments": { + "copy": { + "name": "SOA_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SOA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "SOA" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed SOA record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed SOA record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed SOA record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_SRV": { + "copy": { + "name": "privateDnsZone_SRV", + "count": "[length(coalesce(parameters('srv'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-SRVRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('srv'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'metadata')]" + }, + "srvRecords": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'srvRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "662436323695062210" + }, + "name": "Private DNS Zone SRV record", + "description": "This module deploys a Private DNS Zone SRV record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SRV record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "srvRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of SRV records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "SRV": { + "type": "Microsoft.Network/privateDnsZones/SRV", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "srvRecords": "[parameters('srvRecords')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "SRV_roleAssignments": { + "copy": { + "name": "SRV_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SRV/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "SRV" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed SRV record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed SRV record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed SRV record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_TXT": { + "copy": { + "name": "privateDnsZone_TXT", + "count": "[length(coalesce(parameters('txt'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-TXTRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('txt'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'metadata')]" + }, + "txtRecords": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'txtRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "356727884506799436" + }, + "name": "Private DNS Zone TXT record", + "description": "This module deploys a Private DNS Zone TXT record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the TXT record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "txtRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of TXT records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "TXT": { + "type": "Microsoft.Network/privateDnsZones/TXT", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]", + "txtRecords": "[parameters('txtRecords')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "TXT_roleAssignments": { + "copy": { + "name": "TXT_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/TXT/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "TXT" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed TXT record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed TXT record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed TXT record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_virtualNetworkLinks": { + "copy": { + "name": "privateDnsZone_virtualNetworkLinks", + "count": "[length(coalesce(parameters('virtualNetworkLinks'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-VirtualNetworkLink-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'name'), format('{0}-vnetlink', last(split(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()].virtualNetworkResourceId, '/'))))]" + }, + "virtualNetworkResourceId": { + "value": "[coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()].virtualNetworkResourceId]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'location'), 'global')]" + }, + "registrationEnabled": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'registrationEnabled'), false())]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1713449351614683457" + }, + "name": "Private DNS Zone Virtual Network Link", + "description": "This module deploys a Private DNS Zone Virtual Network Link.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "[format('{0}-vnetlink', last(split(parameters('virtualNetworkResourceId'), '/')))]", + "metadata": { + "description": "Optional. The name of the virtual network link." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. The location of the PrivateDNSZone. Should be global." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "registrationEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "Required. Link to another virtual network resource ID." + } + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "virtualNetworkLink": { + "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "registrationEnabled": "[parameters('registrationEnabled')]", + "virtualNetwork": { + "id": "[parameters('virtualNetworkResourceId')]" + } + }, + "dependsOn": [ + "privateDnsZone" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed virtual network link." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed virtual network link." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/virtualNetworkLinks', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed virtual network link." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('virtualNetworkLink', '2020-06-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private DNS zone was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private DNS zone." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private DNS zone." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones', parameters('name'))]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateDnsZone', '2020-06-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vnet" + ] + }, + "log": { + "condition": "[variables('createNewLog')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-law-{1}', uniqueString(deployment().name, parameters('location')), variables('logName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('logName')]" + }, + "dailyQuotaGb": { + "value": "[coalesce(tryGet(tryGet(parameters('advancedOptions'), 'logAnalyticsWorkspace'), 'dailyQuotaGb'), variables('logDefaultDailyQuotaGb'))]" + }, + "dataRetention": { + "value": "[coalesce(tryGet(tryGet(parameters('advancedOptions'), 'logAnalyticsWorkspace'), 'dataRetention'), variables('logDefaultDataRetention'))]" + }, + "diagnosticSettings": { + "value": [] + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "lock": { + "value": "[parameters('lock')]" + }, + "skuName": { + "value": "PerGB2018" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "17849222501048122703" + }, + "name": "Log Analytics Workspaces", + "description": "This module deploys a Log Analytics Workspace.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "useThisWorkspace": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Instead of using an external reference, use the deployed instance as the target for its diagnostic settings. If set to `true`, the `workspaceResourceId` property is ignored." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Log Analytics workspace." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "skuName": { + "type": "string", + "defaultValue": "PerGB2018", + "allowedValues": [ + "CapacityReservation", + "Free", + "LACluster", + "PerGB2018", + "PerNode", + "Premium", + "Standalone", + "Standard" + ], + "metadata": { + "description": "Optional. The name of the SKU." + } + }, + "skuCapacityReservationLevel": { + "type": "int", + "defaultValue": 100, + "minValue": 100, + "maxValue": 5000, + "metadata": { + "description": "Optional. The capacity reservation level in GB for this workspace, when CapacityReservation sku is selected. Must be in increments of 100 between 100 and 5000." + } + }, + "storageInsightsConfigs": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of storage accounts to be read by the workspace." + } + }, + "linkedServices": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of services to be linked." + } + }, + "linkedStorageAccounts": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Conditional. List of Storage Accounts to be linked. Required if 'forceCmkForQuery' is set to 'true' and 'savedSearches' is not empty." + } + }, + "savedSearches": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Kusto Query Language searches to save." + } + }, + "dataExports": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. LAW data export instances to be deployed." + } + }, + "dataSources": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. LAW data sources to configure." + } + }, + "tables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. LAW custom tables to be deployed." + } + }, + "gallerySolutions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of gallerySolutions to be created in the log analytics workspace." + } + }, + "dataRetention": { + "type": "int", + "defaultValue": 365, + "minValue": 0, + "maxValue": 730, + "metadata": { + "description": "Optional. Number of days data will be retained for." + } + }, + "dailyQuotaGb": { + "type": "int", + "defaultValue": -1, + "minValue": -1, + "metadata": { + "description": "Optional. The workspace daily quota for ingestion." + } + }, + "publicNetworkAccessForIngestion": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. The network access type for accessing Log Analytics ingestion." + } + }, + "publicNetworkAccessForQuery": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. The network access type for accessing Log Analytics query." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." + } + }, + "useResourcePermissions": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Set to 'true' to use resource or workspace permissions and 'false' (or leave empty) to require workspace permissions." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "forceCmkForQuery": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether customer managed storage is mandatory for query management." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), 'SystemAssigned', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', 'None')), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "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')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.operationalinsights-workspace.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "logAnalyticsWorkspace": { + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "features": { + "searchVersion": 1, + "enableLogAccessUsingOnlyResourcePermissions": "[parameters('useResourcePermissions')]" + }, + "sku": { + "name": "[parameters('skuName')]", + "capacityReservationLevel": "[if(equals(parameters('skuName'), 'CapacityReservation'), parameters('skuCapacityReservationLevel'), null())]" + }, + "retentionInDays": "[parameters('dataRetention')]", + "workspaceCapping": { + "dailyQuotaGb": "[parameters('dailyQuotaGb')]" + }, + "publicNetworkAccessForIngestion": "[parameters('publicNetworkAccessForIngestion')]", + "publicNetworkAccessForQuery": "[parameters('publicNetworkAccessForQuery')]", + "forceCmkForQuery": "[parameters('forceCmkForQuery')]" + }, + "identity": "[variables('identity')]" + }, + "logAnalyticsWorkspace_diagnosticSettings": { + "copy": { + "name": "logAnalyticsWorkspace_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "metrics", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics'))))]", + "input": { + "category": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')].category]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')], 'enabled'), true())]", + "timeGrain": null + } + }, + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[if(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'useThisWorkspace'), false()), resourceId('Microsoft.OperationalInsights/workspaces', parameters('name')), tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId'))]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_roleAssignments": { + "copy": { + "name": "logAnalyticsWorkspace_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.OperationalInsights/workspaces', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_storageInsightConfigs": { + "copy": { + "name": "logAnalyticsWorkspace_storageInsightConfigs", + "count": "[length(parameters('storageInsightsConfigs'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-StorageInsightsConfig-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "containers": { + "value": "[tryGet(parameters('storageInsightsConfigs')[copyIndex()], 'containers')]" + }, + "tables": { + "value": "[tryGet(parameters('storageInsightsConfigs')[copyIndex()], 'tables')]" + }, + "storageAccountResourceId": { + "value": "[parameters('storageInsightsConfigs')[copyIndex()].storageAccountResourceId]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "8028201980853199520" + }, + "name": "Log Analytics Workspace Storage Insight Configs", + "description": "This module deploys a Log Analytics Workspace Storage Insight Config.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "[format('{0}-stinsconfig', last(split(parameters('storageAccountResourceId'), '/')))]", + "metadata": { + "description": "Optional. The name of the storage insights config." + } + }, + "storageAccountResourceId": { + "type": "string", + "metadata": { + "description": "Required. The Azure Resource Manager ID of the storage account resource." + } + }, + "containers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The names of the blob containers that the workspace should read." + } + }, + "tables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The names of the Azure tables that the workspace should read." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + } + }, + "resources": { + "storageAccount": { + "existing": true, + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2022-09-01", + "name": "[last(split(parameters('storageAccountResourceId'), '/'))]" + }, + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "storageinsightconfig": { + "type": "Microsoft.OperationalInsights/workspaces/storageInsightConfigs", + "apiVersion": "2020-08-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "containers": "[parameters('containers')]", + "tables": "[parameters('tables')]", + "storageAccount": { + "id": "[parameters('storageAccountResourceId')]", + "key": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', last(split(parameters('storageAccountResourceId'), '/'))), '2022-09-01').keys[0].value]" + } + }, + "dependsOn": [ + "storageAccount", + "workspace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed storage insights configuration." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/storageInsightConfigs', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the storage insight configuration is deployed." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the storage insights configuration." + }, + "value": "[parameters('name')]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_linkedServices": { + "copy": { + "name": "logAnalyticsWorkspace_linkedServices", + "count": "[length(parameters('linkedServices'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-LinkedService-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('linkedServices')[copyIndex()].name]" + }, + "resourceId": { + "value": "[tryGet(parameters('linkedServices')[copyIndex()], 'resourceId')]" + }, + "writeAccessResourceId": { + "value": "[tryGet(parameters('linkedServices')[copyIndex()], 'writeAccessResourceId')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "1524032160953098939" + }, + "name": "Log Analytics Workspace Linked Services", + "description": "This module deploys a Log Analytics Workspace Linked Service.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the link." + } + }, + "resourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access." + } + }, + "writeAccessResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "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." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "linkedService": { + "type": "Microsoft.OperationalInsights/workspaces/linkedServices", + "apiVersion": "2020-08-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "resourceId": "[parameters('resourceId')]", + "writeAccessResourceId": "[if(empty(parameters('writeAccessResourceId')), null(), parameters('writeAccessResourceId'))]" + }, + "dependsOn": [ + "workspace" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed linked service." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed linked service." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/linkedServices', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the linked service is deployed." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_linkedStorageAccounts": { + "copy": { + "name": "logAnalyticsWorkspace_linkedStorageAccounts", + "count": "[length(parameters('linkedStorageAccounts'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-LinkedStorageAccount-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('linkedStorageAccounts')[copyIndex()].name]" + }, + "resourceId": { + "value": "[parameters('linkedStorageAccounts')[copyIndex()].resourceId]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "16040380910189891293" + }, + "name": "Log Analytics Workspace Linked Storage Accounts", + "description": "This module deploys a Log Analytics Workspace Linked Storage Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "allowedValues": [ + "Query", + "Alerts", + "CustomLogs", + "AzureWatson" + ], + "metadata": { + "description": "Required. Name of the link." + } + }, + "resourceId": { + "type": "string", + "metadata": { + "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." + } + } + }, + "resources": [ + { + "type": "Microsoft.OperationalInsights/workspaces/linkedStorageAccounts", + "apiVersion": "2020-08-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "properties": { + "storageAccountIds": [ + "[parameters('resourceId')]" + ] + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed linked storage account." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed linked storage account." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/linkedStorageAccounts', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the linked storage account is deployed." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_savedSearches": { + "copy": { + "name": "logAnalyticsWorkspace_savedSearches", + "count": "[length(parameters('savedSearches'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-SavedSearch-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[format('{0}{1}', parameters('savedSearches')[copyIndex()].name, uniqueString(deployment().name))]" + }, + "etag": { + "value": "[tryGet(parameters('savedSearches')[copyIndex()], 'etag')]" + }, + "displayName": { + "value": "[parameters('savedSearches')[copyIndex()].displayName]" + }, + "category": { + "value": "[parameters('savedSearches')[copyIndex()].category]" + }, + "query": { + "value": "[parameters('savedSearches')[copyIndex()].query]" + }, + "functionAlias": { + "value": "[tryGet(parameters('savedSearches')[copyIndex()], 'functionAlias')]" + }, + "functionParameters": { + "value": "[tryGet(parameters('savedSearches')[copyIndex()], 'functionParameters')]" + }, + "version": { + "value": "[tryGet(parameters('savedSearches')[copyIndex()], 'version')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "7572266675487147820" + }, + "name": "Log Analytics Workspace Saved Searches", + "description": "This module deploys a Log Analytics Workspace Saved Search.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the saved search." + } + }, + "displayName": { + "type": "string", + "metadata": { + "description": "Required. Display name for the search." + } + }, + "category": { + "type": "string", + "metadata": { + "description": "Required. Query category." + } + }, + "query": { + "type": "string", + "metadata": { + "description": "Required. Kusto Query to be stored." + } + }, + "tags": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + }, + "functionAlias": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The function alias if query serves as a function." + } + }, + "functionParameters": { + "type": "string", + "defaultValue": "", + "metadata": { + "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." + } + }, + "version": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The version number of the query language." + } + }, + "etag": { + "type": "string", + "defaultValue": "*", + "metadata": { + "description": "Optional. The ETag of the saved search. To override an existing saved search, use \"*\" or specify the current Etag." + } + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "savedSearch": { + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "apiVersion": "2020-08-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "properties": { + "etag": "[parameters('etag')]", + "tags": "[coalesce(parameters('tags'), createArray())]", + "displayName": "[parameters('displayName')]", + "category": "[parameters('category')]", + "query": "[parameters('query')]", + "functionAlias": "[parameters('functionAlias')]", + "functionParameters": "[parameters('functionParameters')]", + "version": "[parameters('version')]" + }, + "dependsOn": [ + "workspace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed saved search." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the saved search is deployed." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed saved search." + }, + "value": "[parameters('name')]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace", + "logAnalyticsWorkspace_linkedStorageAccounts" + ] + }, + "logAnalyticsWorkspace_dataExports": { + "copy": { + "name": "logAnalyticsWorkspace_dataExports", + "count": "[length(parameters('dataExports'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-DataExport-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "workspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('dataExports')[copyIndex()].name]" + }, + "destination": { + "value": "[tryGet(parameters('dataExports')[copyIndex()], 'destination')]" + }, + "enable": { + "value": "[tryGet(parameters('dataExports')[copyIndex()], 'enable')]" + }, + "tableNames": { + "value": "[tryGet(parameters('dataExports')[copyIndex()], 'tableNames')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "8816832199581598050" + }, + "name": "Log Analytics Workspace Data Exports", + "description": "This module deploys a Log Analytics Workspace Data Export.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "minLength": 4, + "maxLength": 63, + "metadata": { + "description": "Required. The data export rule name." + } + }, + "workspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent workspaces. Required if the template is used in a standalone deployment." + } + }, + "destination": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Destination properties." + } + }, + "enable": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Active when enabled." + } + }, + "tableNames": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']." + } + } + }, + "resources": [ + { + "type": "Microsoft.OperationalInsights/workspaces/dataExports", + "apiVersion": "2020-08-01", + "name": "[format('{0}/{1}', parameters('workspaceName'), parameters('name'))]", + "properties": { + "destination": "[parameters('destination')]", + "enable": "[parameters('enable')]", + "tableNames": "[parameters('tableNames')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the data export." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the data export." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/dataExports', parameters('workspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the data export was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_dataSources": { + "copy": { + "name": "logAnalyticsWorkspace_dataSources", + "count": "[length(parameters('dataSources'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-DataSource-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('dataSources')[copyIndex()].name]" + }, + "kind": { + "value": "[parameters('dataSources')[copyIndex()].kind]" + }, + "linkedResourceId": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'linkedResourceId')]" + }, + "eventLogName": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'eventLogName')]" + }, + "eventTypes": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'eventTypes')]" + }, + "objectName": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'objectName')]" + }, + "instanceName": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'instanceName')]" + }, + "intervalSeconds": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'intervalSeconds')]" + }, + "counterName": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'counterName')]" + }, + "state": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'state')]" + }, + "syslogName": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'syslogName')]" + }, + "syslogSeverities": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'syslogSeverities')]" + }, + "performanceCounters": { + "value": "[tryGet(parameters('dataSources')[copyIndex()], 'performanceCounters')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "10275938611959517944" + }, + "name": "Log Analytics Workspace Datasources", + "description": "This module deploys a Log Analytics Workspace Data Source.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the solution." + } + }, + "kind": { + "type": "string", + "defaultValue": "AzureActivityLog", + "allowedValues": [ + "AzureActivityLog", + "WindowsEvent", + "WindowsPerformanceCounter", + "IISLogs", + "LinuxSyslog", + "LinuxSyslogCollection", + "LinuxPerformanceObject", + "LinuxPerformanceCollection" + ], + "metadata": { + "description": "Optional. The kind of the DataSource." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + }, + "linkedResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the resource to be linked." + } + }, + "eventLogName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Windows event log name to configure when kind is WindowsEvent." + } + }, + "eventTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Windows event types to configure when kind is WindowsEvent." + } + }, + "objectName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "instanceName": { + "type": "string", + "defaultValue": "*", + "metadata": { + "description": "Optional. Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "intervalSeconds": { + "type": "int", + "defaultValue": 60, + "metadata": { + "description": "Optional. Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "performanceCounters": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of counters to configure when the kind is LinuxPerformanceObject." + } + }, + "counterName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Counter name to configure when kind is WindowsPerformanceCounter." + } + }, + "state": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection." + } + }, + "syslogName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. System log to configure when kind is LinuxSyslog." + } + }, + "syslogSeverities": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Severities to configure when kind is LinuxSyslog." + } + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "dataSource": { + "type": "Microsoft.OperationalInsights/workspaces/dataSources", + "apiVersion": "2020-08-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "kind": "[parameters('kind')]", + "tags": "[parameters('tags')]", + "properties": { + "linkedResourceId": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'AzureActivityLog')), parameters('linkedResourceId'), null())]", + "eventLogName": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'WindowsEvent')), parameters('eventLogName'), null())]", + "eventTypes": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'WindowsEvent')), parameters('eventTypes'), null())]", + "objectName": "[if(and(not(empty(parameters('kind'))), or(equals(parameters('kind'), 'WindowsPerformanceCounter'), equals(parameters('kind'), 'LinuxPerformanceObject'))), parameters('objectName'), null())]", + "instanceName": "[if(and(not(empty(parameters('kind'))), or(equals(parameters('kind'), 'WindowsPerformanceCounter'), equals(parameters('kind'), 'LinuxPerformanceObject'))), parameters('instanceName'), null())]", + "intervalSeconds": "[if(and(not(empty(parameters('kind'))), or(equals(parameters('kind'), 'WindowsPerformanceCounter'), equals(parameters('kind'), 'LinuxPerformanceObject'))), parameters('intervalSeconds'), null())]", + "counterName": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'WindowsPerformanceCounter')), parameters('counterName'), null())]", + "state": "[if(and(not(empty(parameters('kind'))), or(or(equals(parameters('kind'), 'IISLogs'), equals(parameters('kind'), 'LinuxSyslogCollection')), equals(parameters('kind'), 'LinuxPerformanceCollection'))), parameters('state'), null())]", + "syslogName": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'LinuxSyslog')), parameters('syslogName'), null())]", + "syslogSeverities": "[if(and(not(empty(parameters('kind'))), or(equals(parameters('kind'), 'LinuxSyslog'), equals(parameters('kind'), 'LinuxPerformanceObject'))), parameters('syslogSeverities'), null())]", + "performanceCounters": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'LinuxPerformanceObject')), parameters('performanceCounters'), null())]" + }, + "dependsOn": [ + "workspace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed data source." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/dataSources', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the data source is deployed." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed data source." + }, + "value": "[parameters('name')]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_tables": { + "copy": { + "name": "logAnalyticsWorkspace_tables", + "count": "[length(parameters('tables'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-Table-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "workspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('tables')[copyIndex()].name]" + }, + "plan": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'plan')]" + }, + "schema": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'schema')]" + }, + "retentionInDays": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'retentionInDays')]" + }, + "totalRetentionInDays": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'totalRetentionInDays')]" + }, + "restoredLogs": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'restoredLogs')]" + }, + "searchResults": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'searchResults')]" + }, + "roleAssignments": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "2417830359794202602" + }, + "name": "Log Analytics Workspace Tables", + "description": "This module deploys a Log Analytics Workspace Table.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the table." + } + }, + "workspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent workspaces. Required if the template is used in a standalone deployment." + } + }, + "plan": { + "type": "string", + "defaultValue": "Analytics", + "allowedValues": [ + "Basic", + "Analytics" + ], + "metadata": { + "description": "Optional. Instruct the system how to handle and charge the logs ingested to this table." + } + }, + "restoredLogs": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Restore parameters." + } + }, + "retentionInDays": { + "type": "int", + "defaultValue": -1, + "minValue": -1, + "maxValue": 730, + "metadata": { + "description": "Optional. The table retention in days, between 4 and 730. Setting this property to -1 will default to the workspace retention." + } + }, + "schema": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Table's schema." + } + }, + "searchResults": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Parameters of the search job that initiated this table." + } + }, + "totalRetentionInDays": { + "type": "int", + "defaultValue": -1, + "minValue": -1, + "maxValue": 2555, + "metadata": { + "description": "Optional. The table total retention in days, between 4 and 2555. Setting this property to -1 will default to table retention." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('workspaceName')]" + }, + "table": { + "type": "Microsoft.OperationalInsights/workspaces/tables", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}', parameters('workspaceName'), parameters('name'))]", + "properties": { + "plan": "[parameters('plan')]", + "restoredLogs": "[parameters('restoredLogs')]", + "retentionInDays": "[parameters('retentionInDays')]", + "schema": "[parameters('schema')]", + "searchResults": "[parameters('searchResults')]", + "totalRetentionInDays": "[parameters('totalRetentionInDays')]" + }, + "dependsOn": [ + "workspace" + ] + }, + "table_roleAssignments": { + "copy": { + "name": "table_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}/tables/{1}', parameters('workspaceName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.OperationalInsights/workspaces/tables', parameters('workspaceName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "table" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the table." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the table." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/tables', parameters('workspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the table was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_solutions": { + "copy": { + "name": "logAnalyticsWorkspace_solutions", + "count": "[length(parameters('gallerySolutions'))]" + }, + "condition": "[not(empty(parameters('gallerySolutions')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-Solution-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('gallerySolutions')[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "product": { + "value": "[tryGet(parameters('gallerySolutions')[copyIndex()], 'product')]" + }, + "publisher": { + "value": "[tryGet(parameters('gallerySolutions')[copyIndex()], 'publisher')]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(parameters('gallerySolutions')[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "18444780972506374592" + }, + "name": "Operations Management Solutions", + "description": "This module deploys an Operations Management Solution.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the solution. For Microsoft published gallery solution the target solution resource name will be composed as `{name}({logAnalyticsWorkspaceName})`." + } + }, + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Log Analytics workspace where the solution will be deployed/enabled." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "product": { + "type": "string", + "defaultValue": "OMSGallery", + "metadata": { + "description": "Optional. The product of the deployed solution. For Microsoft published gallery solution it should be `OMSGallery` and the target solution resource product will be composed as `OMSGallery/{name}`. For third party solution, it can be anything. This is case sensitive." + } + }, + "publisher": { + "type": "string", + "defaultValue": "Microsoft", + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "solutionName": "[if(equals(parameters('publisher'), 'Microsoft'), format('{0}({1})', parameters('name'), parameters('logAnalyticsWorkspaceName')), parameters('name'))]", + "solutionProduct": "[if(equals(parameters('publisher'), 'Microsoft'), format('OMSGallery/{0}', parameters('name')), parameters('product'))]" + }, + "resources": [ + { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.operationsmanagement-solution.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + { + "type": "Microsoft.OperationsManagement/solutions", + "apiVersion": "2015-11-01-preview", + "name": "[variables('solutionName')]", + "location": "[parameters('location')]", + "properties": { + "workspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]" + }, + "plan": { + "name": "[variables('solutionName')]", + "promotionCode": "", + "product": "[variables('solutionProduct')]", + "publisher": "[parameters('publisher')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed solution." + }, + "value": "[variables('solutionName')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed solution." + }, + "value": "[resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the solution is deployed." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference(resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName')), '2015-11-01-preview', 'full').location]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed log analytics workspace." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed log analytics workspace." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed log analytics workspace." + }, + "value": "[parameters('name')]" + }, + "logAnalyticsWorkspaceId": { + "type": "string", + "metadata": { + "description": "The ID associated with the workspace." + }, + "value": "[reference('logAnalyticsWorkspace').customerId]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('logAnalyticsWorkspace', '2022-10-01', 'full').location]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('logAnalyticsWorkspace', '2022-10-01', 'full'), 'identity'), 'principalId'), '')]" + } + } + } + } + }, + "kv": { + "condition": "[variables('createNewKV')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-vault-{1}', uniqueString(deployment().name, parameters('location')), variables('kvName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('kvName')]" + }, + "createMode": { + "value": "[coalesce(tryGet(tryGet(parameters('advancedOptions'), 'keyVault'), 'createMode'), variables('kvDefaultCreateMode'))]" + }, + "diagnosticSettings": { + "value": [ + { + "name": "[variables('diagnosticSettingsName')]", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "logCategoriesAndGroups": [ + { + "categoryGroup": "audit" + }, + { + "categoryGroup": "allLogs" + } + ], + "workspaceResourceId": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).resourceId]" + } + ] + }, + "enablePurgeProtection": { + "value": "[coalesce(tryGet(tryGet(parameters('advancedOptions'), 'keyVault'), 'enablePurgeProtection'), variables('kvDefaultEnablePurgeProtection'))]" + }, + "enableRbacAuthorization": { + "value": true + }, + "enableSoftDelete": { + "value": "[coalesce(tryGet(tryGet(parameters('advancedOptions'), 'keyVault'), 'enableSoftDelete'), variables('kvDefaultEnableSoftDelete'))]" + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "enableVaultForDeployment": { + "value": false + }, + "enableVaultForTemplateDeployment": { + "value": false + }, + "enableVaultForDiskEncryption": { + "value": false + }, + "location": { + "value": "[parameters('location')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "networkAcls": { + "value": { + "bypass": "None", + "defaultAction": "Deny", + "ipRules": "[variables('kvIpRules')]" + } + }, + "privateEndpoints": { + "value": [ + { + "name": "[format('{0}-kv-pep', parameters('name'))]", + "location": "[parameters('location')]", + "subnetResourceId": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).subnetResourceIdPrivateLink]", + "privateDnsZoneGroup": "[if(variables('createNewVNET'), createObject('privateDnsZoneGroupConfigs', createArray(createObject('privateDnsZoneResourceId', reference('dnsZoneKv').outputs.resourceId.value))), null())]", + "tags": "[parameters('tags')]", + "enableTelemetry": "[parameters('enableTelemetry')]", + "lock": "[parameters('lock')]", + "roleAssignments": "[if(empty(variables('ownerRoleAssignments')), createArray(), variables('ownerRoleAssignments'))]" + } + ] + }, + "publicNetworkAccess": "[if(empty(variables('kvIpRules')), createObject('value', 'Disabled'), createObject('value', 'Enabled'))]", + "roleAssignments": "[if(empty(variables('kvMultipleRoleAssignments')), createObject('value', createArray()), createObject('value', variables('kvMultipleRoleAssignments')))]", + "sku": "[if(equals(tryGet(tryGet(parameters('advancedOptions'), 'keyVault'), 'sku'), 'standard'), createObject('value', 'standard'), createObject('value', variables('kvDefaultSku')))]", + "softDeleteRetentionInDays": { + "value": "[coalesce(tryGet(tryGet(parameters('advancedOptions'), 'keyVault'), 'softDeleteRetentionInDays'), variables('kvDefaultSoftDeleteRetentionInDays'))]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "10085839006881327962" + }, + "name": "Key Vaults", + "description": "This module deploys a Key Vault.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "accessPoliciesType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tenant ID that is used for authenticating requests to the key vault." + } + }, + "objectId": { + "type": "string", + "metadata": { + "description": "Required. The object ID of a user, service principal or security group in the tenant for the vault." + } + }, + "applicationId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Application ID of the client making request on behalf of a principal." + } + }, + "permissions": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "create", + "decrypt", + "delete", + "encrypt", + "get", + "getrotationpolicy", + "import", + "list", + "purge", + "recover", + "release", + "restore", + "rotate", + "setrotationpolicy", + "sign", + "unwrapKey", + "update", + "verify", + "wrapKey" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to keys." + } + }, + "secrets": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "delete", + "get", + "list", + "purge", + "recover", + "restore", + "set" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to secrets." + } + }, + "certificates": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "create", + "delete", + "deleteissuers", + "get", + "getissuers", + "import", + "list", + "listissuers", + "managecontacts", + "manageissuers", + "purge", + "recover", + "restore", + "setissuers", + "update" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to certificates." + } + }, + "storage": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "delete", + "deletesas", + "get", + "getsas", + "list", + "listsas", + "purge", + "recover", + "regeneratekey", + "restore", + "set", + "setsas", + "update" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to storage accounts." + } + } + }, + "metadata": { + "description": "Required. Permissions the identity has for keys, secrets and certificates." + } + } + } + }, + "nullable": true + }, + "secretsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributes": { + "type": "object", + "properties": { + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Defines whether the secret is enabled or disabled." + } + }, + "exp": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Defines when the secret will become invalid. Defined in seconds since 1970-01-01T00:00:00Z." + } + }, + "nbf": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. If set, defines the date from which onwards the secret becomes valid. Defined in seconds since 1970-01-01T00:00:00Z." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Contains attributes of the secret." + } + }, + "contentType": { + "type": "string", + "nullable": true, + "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." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + } + }, + "nullable": true + }, + "keysType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the key." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributes": { + "type": "object", + "properties": { + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Defines whether the key is enabled or disabled." + } + }, + "exp": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Defines when the key will become invalid. Defined in seconds since 1970-01-01T00:00:00Z." + } + }, + "nbf": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. If set, defines the date from which onwards the key becomes valid. Defined in seconds since 1970-01-01T00:00:00Z." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Contains attributes of the key." + } + }, + "curveName": { + "type": "string", + "allowedValues": [ + "P-256", + "P-256K", + "P-384", + "P-521" + ], + "nullable": true, + "metadata": { + "description": "Optional. The elliptic curve name. Only works if \"keySize\" equals \"EC\" or \"EC-HSM\". Default is \"P-256\"." + } + }, + "keyOps": { + "type": "array", + "allowedValues": [ + "decrypt", + "encrypt", + "import", + "release", + "sign", + "unwrapKey", + "verify", + "wrapKey" + ], + "nullable": true, + "metadata": { + "description": "Optional. The allowed operations on this key." + } + }, + "keySize": { + "type": "int", + "allowedValues": [ + 2048, + 3072, + 4096 + ], + "nullable": true, + "metadata": { + "description": "Optional. The key size in bits. Only works if \"keySize\" equals \"RSA\" or \"RSA-HSM\". Default is \"4096\"." + } + }, + "kty": { + "type": "string", + "allowedValues": [ + "EC", + "EC-HSM", + "RSA", + "RSA-HSM" + ], + "nullable": true, + "metadata": { + "description": "Optional. The type of the key. Default is \"EC\"." + } + }, + "releasePolicy": { + "type": "object", + "properties": { + "contentType": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Content type and version of key release policy." + } + }, + "data": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Blob encoding the policy rules under which the key can be released." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Key release policy." + } + }, + "rotationPolicy": { + "$ref": "#/definitions/rotationPoliciesType", + "nullable": true, + "metadata": { + "description": "Optional. Key rotation policy." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + } + }, + "nullable": true + }, + "rotationPoliciesType": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "properties": { + "expiryTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The expiration time for the new key version. It should be in ISO8601 format. Eg: \"P90D\", \"P1Y\"." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The attributes of key rotation policy." + } + }, + "lifetimeActions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "action": { + "type": "object", + "properties": { + "type": { + "type": "string", + "allowedValues": [ + "Notify", + "Rotate" + ], + "nullable": true, + "metadata": { + "description": "Optional. The type of action." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The action of key rotation policy lifetimeAction." + } + }, + "trigger": { + "type": "object", + "properties": { + "timeAfterCreate": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The time duration after key creation to rotate the key. It only applies to rotate. It will be in ISO 8601 duration format. Eg: \"P90D\", \"P1Y\"." + } + }, + "timeBeforeExpiry": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The time duration before key expiring to rotate or notify. It will be in ISO 8601 duration format. Eg: \"P90D\", \"P1Y\"." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The trigger of key rotation policy lifetimeAction." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The lifetimeActions for key rotation action." + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "maxLength": 24, + "metadata": { + "description": "Required. Name of the Key Vault. Must be globally unique." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "accessPolicies": { + "$ref": "#/definitions/accessPoliciesType", + "metadata": { + "description": "Optional. All access policies to create." + } + }, + "secrets": { + "$ref": "#/definitions/secretsType", + "nullable": true, + "metadata": { + "description": "Optional. All secrets to create." + } + }, + "keys": { + "$ref": "#/definitions/keysType", + "nullable": true, + "metadata": { + "description": "Optional. All keys to create." + } + }, + "enableVaultForDeployment": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Specifies if the vault is enabled for deployment by script or compute." + } + }, + "enableVaultForTemplateDeployment": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Specifies if the vault is enabled for a template deployment." + } + }, + "enableVaultForDiskEncryption": { + "type": "bool", + "defaultValue": true, + "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": true, + "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. 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. 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": true, + "metadata": { + "description": "Optional. Provide 'true' to enable Key Vault's purge protection feature." + } + }, + "sku": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "premium", + "standard" + ], + "metadata": { + "description": "Optional. Specifies the SKU for the vault." + } + }, + "networkAcls": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Rules governing the accessibility of the resource from specific network locations." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and networkAcls are not set." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + }, + { + "name": "formattedAccessPolicies", + "count": "[length(coalesce(parameters('accessPolicies'), createArray()))]", + "input": { + "applicationId": "[coalesce(tryGet(coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')], 'applicationId'), '')]", + "objectId": "[coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')].objectId]", + "permissions": "[coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[coalesce(tryGet(coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')], 'tenantId'), tenant().tenantId)]" + } + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "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 Certificate User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db79e9a7-68ee-4b58-9aeb-b90e7c24fcba')]", + "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')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.keyvault-vault.{0}.{1}', replace('0.9.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "keyVault": { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('name')]", + "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('sku')]", + "family": "A" + }, + "networkAcls": "[if(not(empty(coalesce(parameters('networkAcls'), createObject()))), createObject('bypass', tryGet(parameters('networkAcls'), 'bypass'), 'defaultAction', tryGet(parameters('networkAcls'), 'defaultAction'), 'virtualNetworkRules', coalesce(tryGet(parameters('networkAcls'), 'virtualNetworkRules'), createArray()), 'ipRules', coalesce(tryGet(parameters('networkAcls'), 'ipRules'), createArray())), null())]", + "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), parameters('publicNetworkAccess'), if(and(not(empty(coalesce(parameters('privateEndpoints'), createArray()))), empty(coalesce(parameters('networkAcls'), createObject()))), 'Disabled', null()))]" + } + }, + "keyVault_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_diagnosticSettings": { + "copy": { + "name": "keyVault_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "metrics", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics'))))]", + "input": { + "category": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')].category]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')], 'enabled'), true())]", + "timeGrain": null + } + }, + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_roleAssignments": { + "copy": { + "name": "keyVault_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.KeyVault/vaults', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_accessPolicies": { + "condition": "[not(empty(parameters('accessPolicies')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-KeyVault-AccessPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[parameters('name')]" + }, + "accessPolicies": { + "value": "[parameters('accessPolicies')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "7494731697751039419" + }, + "name": "Key Vault Access Policies", + "description": "This module deploys a Key Vault Access Policy.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "accessPoliciesType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tenant ID that is used for authenticating requests to the key vault." + } + }, + "objectId": { + "type": "string", + "metadata": { + "description": "Required. The object ID of a user, service principal or security group in the tenant for the vault." + } + }, + "applicationId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Application ID of the client making request on behalf of a principal." + } + }, + "permissions": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "create", + "decrypt", + "delete", + "encrypt", + "get", + "getrotationpolicy", + "import", + "list", + "purge", + "recover", + "release", + "restore", + "rotate", + "setrotationpolicy", + "sign", + "unwrapKey", + "update", + "verify", + "wrapKey" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to keys." + } + }, + "secrets": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "delete", + "get", + "list", + "purge", + "recover", + "restore", + "set" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to secrets." + } + }, + "certificates": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "create", + "delete", + "deleteissuers", + "get", + "getissuers", + "import", + "list", + "listissuers", + "managecontacts", + "manageissuers", + "purge", + "recover", + "restore", + "setissuers", + "update" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to certificates." + } + }, + "storage": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "delete", + "deletesas", + "get", + "getsas", + "list", + "listsas", + "purge", + "recover", + "regeneratekey", + "restore", + "set", + "setsas", + "update" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to storage accounts." + } + } + }, + "metadata": { + "description": "Required. Permissions the identity has for keys, secrets and certificates." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent key vault. Required if the template is used in a standalone deployment." + } + }, + "accessPolicies": { + "$ref": "#/definitions/accessPoliciesType", + "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." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedAccessPolicies", + "count": "[length(coalesce(parameters('accessPolicies'), createArray()))]", + "input": { + "applicationId": "[coalesce(tryGet(coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')], 'applicationId'), '')]", + "objectId": "[coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')].objectId]", + "permissions": "[coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[coalesce(tryGet(coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')], 'tenantId'), tenant().tenantId)]" + } + } + ] + }, + "resources": { + "keyVault": { + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('keyVaultName')]" + }, + "policies": { + "type": "Microsoft.KeyVault/vaults/accessPolicies", + "apiVersion": "2022-07-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), 'add')]", + "properties": { + "accessPolicies": "[variables('formattedAccessPolicies')]" + }, + "dependsOn": [ + "keyVault" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the access policies assignment was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the access policies assignment." + }, + "value": "add" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the access policies assignment." + }, + "value": "[resourceId('Microsoft.KeyVault/vaults/accessPolicies', parameters('keyVaultName'), 'add')]" + } + } + } + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_secrets": { + "copy": { + "name": "keyVault_secrets", + "count": "[length(coalesce(parameters('secrets'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-KeyVault-Secret-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('secrets'), createArray())[copyIndex()].name]" + }, + "value": { + "value": "[coalesce(parameters('secrets'), createArray())[copyIndex()].value]" + }, + "keyVaultName": { + "value": "[parameters('name')]" + }, + "attributesEnabled": { + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributes'), 'enabled')]" + }, + "attributesExp": { + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributes'), 'exp')]" + }, + "attributesNbf": { + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributes'), 'nbf')]" + }, + "contentType": { + "value": "[tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'contentType')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "114626909766354577" + }, + "name": "Key Vault Secrets", + "description": "This module deploys a Key Vault Secret.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent key vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "nullable": true, + "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", + "nullable": true, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "contentType": { + "type": "securestring", + "nullable": true, + "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." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "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')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "keyVault": { + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('keyVaultName')]" + }, + "secret": { + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2022-07-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "contentType": "[parameters('contentType')]", + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[parameters('attributesExp')]", + "nbf": "[parameters('attributesNbf')]" + }, + "value": "[parameters('value')]" + }, + "dependsOn": [ + "keyVault" + ] + }, + "secret_roleAssignments": { + "copy": { + "name": "secret_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/secrets/{1}', parameters('keyVaultName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "secret" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the secret." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the secret." + }, + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the secret was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_keys": { + "copy": { + "name": "keyVault_keys", + "count": "[length(coalesce(parameters('keys'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-KeyVault-Key-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('keys'), createArray())[copyIndex()].name]" + }, + "keyVaultName": { + "value": "[parameters('name')]" + }, + "attributesEnabled": { + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'enabled')]" + }, + "attributesExp": { + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'exp')]" + }, + "attributesNbf": { + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'nbf')]" + }, + "curveName": "[if(and(not(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA')), not(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA-HSM'))), createObject('value', coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'curveName'), 'P-256')), createObject('value', null()))]", + "keyOps": { + "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'keyOps')]" + }, + "keySize": "[if(or(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA'), equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA-HSM')), createObject('value', coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'keySize'), 4096)), createObject('value', null()))]", + "releasePolicy": { + "value": "[coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'releasePolicy'), createObject())]" + }, + "kty": { + "value": "[coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'EC')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "rotationPolicy": { + "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'rotationPolicy')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "14269695922191217406" + }, + "name": "Key Vault Keys", + "description": "This module deploys a Key Vault Key.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent key vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the key." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "nullable": true, + "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", + "nullable": true, + "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", + "nullable": true, + "allowedValues": [ + "decrypt", + "encrypt", + "import", + "sign", + "unwrapKey", + "verify", + "wrapKey" + ], + "metadata": { + "description": "Optional. Array of JsonWebKeyOperation." + } + }, + "keySize": { + "type": "int", + "nullable": true, + "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." + } + }, + "releasePolicy": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Key release policy." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "rotationPolicy": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Key rotation policy properties object." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "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')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "keyVault": { + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('keyVaultName')]" + }, + "key": { + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2022-07-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[parameters('attributesExp')]", + "nbf": "[parameters('attributesNbf')]" + }, + "curveName": "[parameters('curveName')]", + "keyOps": "[parameters('keyOps')]", + "keySize": "[parameters('keySize')]", + "kty": "[parameters('kty')]", + "rotationPolicy": "[coalesce(parameters('rotationPolicy'), createObject())]", + "release_policy": "[coalesce(parameters('releasePolicy'), createObject())]" + }, + "dependsOn": [ + "keyVault" + ] + }, + "key_roleAssignments": { + "copy": { + "name": "key_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/keys/{1}', parameters('keyVaultName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "key" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the key." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the key." + }, + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the key was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_privateEndpoints": { + "copy": { + "name": "keyVault_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-keyVault-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'resourceGroupName'), '')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.KeyVault/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault'), copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.KeyVault/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.KeyVault/vaults', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault')))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.KeyVault/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.KeyVault/vaults', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault')), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroup": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1277254088602407590" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "5805178546717255803" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDnsZoneConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", + "input": { + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" + } + } + } + ] + }, + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" + } + } + } + }, + "dependsOn": [ + "keyVault" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the key vault." + }, + "value": "[resourceId('Microsoft.KeyVault/vaults', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the key vault was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the key vault." + }, + "value": "[parameters('name')]" + }, + "uri": { + "type": "string", + "metadata": { + "description": "The URI of the key vault." + }, + "value": "[reference('keyVault').vaultUri]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('keyVault', '2022-07-01', 'full').location]" + }, + "privateEndpoints": { + "type": "array", + "metadata": { + "description": "The private endpoints of the key vault." + }, + "copy": { + "count": "[length(if(not(empty(parameters('privateEndpoints'))), array(parameters('privateEndpoints')), createArray()))]", + "input": { + "name": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + } + } + } + } + } + }, + "dependsOn": [ + "dnsZoneKv", + "log", + "logExisting", + "vnet", + "vnetExisting" + ] + }, + "dnsZoneKv": { + "condition": "[and(variables('createNewVNET'), variables('createNewKV'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-zone-{1}', uniqueString(deployment().name, parameters('location')), variables('privateDnsZoneNameKv'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('privateDnsZoneNameKv')]" + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "global" + }, + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "lock": { + "value": "[parameters('lock')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "virtualNetworkLinks": { + "value": [ + { + "registrationEnabled": false, + "virtualNetworkResourceId": "[reference('vnet').outputs.resourceId.value]" + } + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "5518185016108244461" + }, + "name": "Private DNS Zones", + "description": "This module deploys a Private DNS zone.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "aType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "aRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipv4Address": { + "type": "string", + "metadata": { + "description": "Required. The IPv4 address of this A record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of A records in the record set." + } + } + } + }, + "nullable": true + }, + "aaaaType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "aaaaRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipv6Address": { + "type": "string", + "metadata": { + "description": "Required. The IPv6 address of this AAAA record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of AAAA records in the record set." + } + } + } + }, + "nullable": true + }, + "cnameType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "cnameRecord": { + "type": "object", + "properties": { + "cname": { + "type": "string", + "metadata": { + "description": "Required. The canonical name of the CNAME record." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The CNAME record in the record set." + } + } + } + }, + "nullable": true + }, + "mxType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "mxRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "exchange": { + "type": "string", + "metadata": { + "description": "Required. The domain name of the mail host for this MX record." + } + }, + "preference": { + "type": "int", + "metadata": { + "description": "Required. The preference value for this MX record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of MX records in the record set." + } + } + } + }, + "nullable": true + }, + "ptrType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "ptrRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ptrdname": { + "type": "string", + "metadata": { + "description": "Required. The PTR target domain name for this PTR record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of PTR records in the record set." + } + } + } + }, + "nullable": true + }, + "soaType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "soaRecord": { + "type": "object", + "properties": { + "email": { + "type": "string", + "metadata": { + "description": "Required. The email contact for this SOA record." + } + }, + "expireTime": { + "type": "int", + "metadata": { + "description": "Required. The expire time for this SOA record." + } + }, + "host": { + "type": "string", + "metadata": { + "description": "Required. The domain name of the authoritative name server for this SOA record." + } + }, + "minimumTtl": { + "type": "int", + "metadata": { + "description": "Required. The minimum value for this SOA record. By convention this is used to determine the negative caching duration." + } + }, + "refreshTime": { + "type": "int", + "metadata": { + "description": "Required. The refresh value for this SOA record." + } + }, + "retryTime": { + "type": "int", + "metadata": { + "description": "Required. The retry time for this SOA record." + } + }, + "serialNumber": { + "type": "int", + "metadata": { + "description": "Required. The serial number for this SOA record." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The SOA record in the record set." + } + } + } + }, + "nullable": true + }, + "srvType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "srvRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "priority": { + "type": "int", + "metadata": { + "description": "Required. The priority value for this SRV record." + } + }, + "weight": { + "type": "int", + "metadata": { + "description": "Required. The weight value for this SRV record." + } + }, + "port": { + "type": "int", + "metadata": { + "description": "Required. The port value for this SRV record." + } + }, + "target": { + "type": "string", + "metadata": { + "description": "Required. The target domain name for this SRV record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of SRV records in the record set." + } + } + } + }, + "nullable": true + }, + "txtType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "txtRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The text value of this TXT record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of TXT records in the record set." + } + } + } + }, + "nullable": true + }, + "virtualNetworkLinkType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 80, + "metadata": { + "description": "Optional. The resource name." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the virtual network to link." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Azure Region where the resource lives." + } + }, + "registrationEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Private DNS zone name." + } + }, + "a": { + "$ref": "#/definitions/aType", + "metadata": { + "description": "Optional. Array of A records." + } + }, + "aaaa": { + "$ref": "#/definitions/aaaaType", + "metadata": { + "description": "Optional. Array of AAAA records." + } + }, + "cname": { + "$ref": "#/definitions/cnameType", + "metadata": { + "description": "Optional. Array of CNAME records." + } + }, + "mx": { + "$ref": "#/definitions/mxType", + "metadata": { + "description": "Optional. Array of MX records." + } + }, + "ptr": { + "$ref": "#/definitions/ptrType", + "metadata": { + "description": "Optional. Array of PTR records." + } + }, + "soa": { + "$ref": "#/definitions/soaType", + "metadata": { + "description": "Optional. Array of SOA records." + } + }, + "srv": { + "$ref": "#/definitions/srvType", + "metadata": { + "description": "Optional. Array of SRV records." + } + }, + "txt": { + "$ref": "#/definitions/txtType", + "metadata": { + "description": "Optional. Array of TXT records." + } + }, + "virtualNetworkLinks": { + "$ref": "#/definitions/virtualNetworkLinkType", + "metadata": { + "description": "Optional. Array of custom objects describing vNet links of the DNS zone. Each object should contain properties 'virtualNetworkResourceId' 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." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. The location of the PrivateDNSZone. Should be global." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privatednszone.{0}.{1}', replace('0.6.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateDnsZone": { + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + "privateDnsZone_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_roleAssignments": { + "copy": { + "name": "privateDnsZone_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_A": { + "copy": { + "name": "privateDnsZone_A", + "count": "[length(coalesce(parameters('a'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-ARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('a'), createArray())[copyIndex()].name]" + }, + "aRecords": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'aRecords')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1641889417618452692" + }, + "name": "Private DNS Zone A record", + "description": "This module deploys a Private DNS Zone A record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the A record." + } + }, + "aRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of A records in the record set." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "A": { + "type": "Microsoft.Network/privateDnsZones/A", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "aRecords": "[parameters('aRecords')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "A_roleAssignments": { + "copy": { + "name": "A_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/A/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "A" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed A record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed A record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed A record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_AAAA": { + "copy": { + "name": "privateDnsZone_AAAA", + "count": "[length(coalesce(parameters('aaaa'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-AAAARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('aaaa'), createArray())[copyIndex()].name]" + }, + "aaaaRecords": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'aaaaRecords')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "17163414995652446126" + }, + "name": "Private DNS Zone AAAA record", + "description": "This module deploys a Private DNS Zone AAAA record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the AAAA record." + } + }, + "aaaaRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of AAAA records in the record set." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "AAAA": { + "type": "Microsoft.Network/privateDnsZones/AAAA", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "aaaaRecords": "[parameters('aaaaRecords')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "AAAA_roleAssignments": { + "copy": { + "name": "AAAA_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/AAAA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "AAAA" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed AAAA record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed AAAA record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed AAAA record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_CNAME": { + "copy": { + "name": "privateDnsZone_CNAME", + "count": "[length(coalesce(parameters('cname'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-CNAMERecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('cname'), createArray())[copyIndex()].name]" + }, + "cnameRecord": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'cnameRecord')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "2493714129104385633" + }, + "name": "Private DNS Zone CNAME record", + "description": "This module deploys a Private DNS Zone CNAME record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the CNAME record." + } + }, + "cnameRecord": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. A CNAME record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "CNAME": { + "type": "Microsoft.Network/privateDnsZones/CNAME", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "cnameRecord": "[parameters('cnameRecord')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "CNAME_roleAssignments": { + "copy": { + "name": "CNAME_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/CNAME/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "CNAME" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed CNAME record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed CNAME record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed CNAME record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_MX": { + "copy": { + "name": "privateDnsZone_MX", + "count": "[length(coalesce(parameters('mx'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-MXRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('mx'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'metadata')]" + }, + "mxRecords": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'mxRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "10928449924272756679" + }, + "name": "Private DNS Zone MX record", + "description": "This module deploys a Private DNS Zone MX record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the MX record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "mxRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of MX records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "MX": { + "type": "Microsoft.Network/privateDnsZones/MX", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "mxRecords": "[parameters('mxRecords')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "MX_roleAssignments": { + "copy": { + "name": "MX_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/MX/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "MX" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed MX record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed MX record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed MX record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_PTR": { + "copy": { + "name": "privateDnsZone_PTR", + "count": "[length(coalesce(parameters('ptr'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-PTRRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('ptr'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'metadata')]" + }, + "ptrRecords": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'ptrRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "13191587152357386110" + }, + "name": "Private DNS Zone PTR record", + "description": "This module deploys a Private DNS Zone PTR record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the PTR record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ptrRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of PTR records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "PTR": { + "type": "Microsoft.Network/privateDnsZones/PTR", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "ptrRecords": "[parameters('ptrRecords')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "PTR_roleAssignments": { + "copy": { + "name": "PTR_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/PTR/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "PTR" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed PTR record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed PTR record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed PTR record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_SOA": { + "copy": { + "name": "privateDnsZone_SOA", + "count": "[length(coalesce(parameters('soa'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-SOARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('soa'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'metadata')]" + }, + "soaRecord": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'soaRecord')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "12872700379964561295" + }, + "name": "Private DNS Zone SOA record", + "description": "This module deploys a Private DNS Zone SOA record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SOA record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "soaRecord": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. A SOA record." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "SOA": { + "type": "Microsoft.Network/privateDnsZones/SOA", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "soaRecord": "[parameters('soaRecord')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "SOA_roleAssignments": { + "copy": { + "name": "SOA_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SOA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "SOA" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed SOA record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed SOA record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed SOA record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_SRV": { + "copy": { + "name": "privateDnsZone_SRV", + "count": "[length(coalesce(parameters('srv'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-SRVRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('srv'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'metadata')]" + }, + "srvRecords": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'srvRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "12918383495773487180" + }, + "name": "Private DNS Zone SRV record", + "description": "This module deploys a Private DNS Zone SRV record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SRV record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "srvRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of SRV records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "SRV": { + "type": "Microsoft.Network/privateDnsZones/SRV", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "srvRecords": "[parameters('srvRecords')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "SRV_roleAssignments": { + "copy": { + "name": "SRV_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SRV/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "SRV" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed SRV record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed SRV record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed SRV record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_TXT": { + "copy": { + "name": "privateDnsZone_TXT", + "count": "[length(coalesce(parameters('txt'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-TXTRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('txt'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'metadata')]" + }, + "txtRecords": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'txtRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "128006490354221158" + }, + "name": "Private DNS Zone TXT record", + "description": "This module deploys a Private DNS Zone TXT record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the TXT record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "txtRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of TXT records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "TXT": { + "type": "Microsoft.Network/privateDnsZones/TXT", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]", + "txtRecords": "[parameters('txtRecords')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "TXT_roleAssignments": { + "copy": { + "name": "TXT_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/TXT/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "TXT" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed TXT record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed TXT record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed TXT record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_virtualNetworkLinks": { + "copy": { + "name": "privateDnsZone_virtualNetworkLinks", + "count": "[length(coalesce(parameters('virtualNetworkLinks'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-VirtualNetworkLink-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'name'), format('{0}-vnetlink', last(split(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()].virtualNetworkResourceId, '/'))))]" + }, + "virtualNetworkResourceId": { + "value": "[coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()].virtualNetworkResourceId]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'location'), 'global')]" + }, + "registrationEnabled": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'registrationEnabled'), false())]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1713449351614683457" + }, + "name": "Private DNS Zone Virtual Network Link", + "description": "This module deploys a Private DNS Zone Virtual Network Link.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "[format('{0}-vnetlink', last(split(parameters('virtualNetworkResourceId'), '/')))]", + "metadata": { + "description": "Optional. The name of the virtual network link." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. The location of the PrivateDNSZone. Should be global." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "registrationEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "Required. Link to another virtual network resource ID." + } + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "virtualNetworkLink": { + "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "registrationEnabled": "[parameters('registrationEnabled')]", + "virtualNetwork": { + "id": "[parameters('virtualNetworkResourceId')]" + } + }, + "dependsOn": [ + "privateDnsZone" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed virtual network link." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed virtual network link." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/virtualNetworkLinks', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed virtual network link." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('virtualNetworkLink', '2020-06-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private DNS zone was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private DNS zone." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private DNS zone." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones', parameters('name'))]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateDnsZone', '2020-06-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vnet" + ] + }, + "accessConnector": { + "condition": "[parameters('enableDatabricks')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-connector-{1}', uniqueString(deployment().name, parameters('location')), variables('dbwAccessConnectorName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('dbwAccessConnectorName')]" + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "managedIdentities": { + "value": { + "systemAssigned": true + } + }, + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "14471774374628354564" + }, + "name": "Azure Databricks Access Connectors", + "description": "This module deploys an Azure Databricks Access Connector.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Azure Databricks access connector to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', 'None')), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), createObject('type', 'None'))]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.databricks-accessconnector.{0}.{1}', replace('0.3.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "accessConnector": { + "type": "Microsoft.Databricks/accessConnectors", + "apiVersion": "2022-10-01-preview", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "properties": {} + }, + "accessConnector_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Databricks/accessConnectors/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "accessConnector" + ] + }, + "accessConnector_roleAssignments": { + "copy": { + "name": "accessConnector_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Databricks/accessConnectors/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Databricks/accessConnectors', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "accessConnector" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed access connector." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed access connector." + }, + "value": "[resourceId('Microsoft.Databricks/accessConnectors', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed access connector." + }, + "value": "[resourceGroup().name]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('accessConnector', '2022-10-01-preview', 'full'), 'identity'), 'principalId'), '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('accessConnector', '2022-10-01-preview', 'full').location]" + } + } + } + } + }, + "dbw": { + "condition": "[parameters('enableDatabricks')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-workspace-{1}', uniqueString(deployment().name, parameters('location')), variables('dbwName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('dbwName')]" + }, + "accessConnectorResourceId": { + "value": "[reference('accessConnector').outputs.resourceId.value]" + }, + "customPublicSubnetName": "[if(variables('createNewVNET'), createObject('value', variables('subnetNameDbwFrontend')), createObject('value', tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend')))]", + "customPrivateSubnetName": "[if(variables('createNewVNET'), createObject('value', variables('subnetNameDbwBackend')), createObject('value', tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend')))]", + "customVirtualNetworkResourceId": { + "value": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).resourceId]" + }, + "diagnosticSettings": { + "value": [ + { + "name": "[variables('diagnosticSettingsName')]", + "logCategoriesAndGroups": [ + { + "categoryGroup": "allLogs" + } + ], + "workspaceResourceId": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).resourceId]" + } + ] + }, + "disablePublicIp": { + "value": true + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "managedResourceGroupResourceId": { + "value": null + }, + "prepareEncryption": { + "value": true + }, + "privateEndpoints": { + "value": [ + { + "name": "[format('{0}-dbw-ui-pep', parameters('name'))]", + "location": "[parameters('location')]", + "service": "databricks_ui_api", + "subnetResourceId": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).subnetResourceIdPrivateLink]", + "privateDnsZoneGroup": "[if(variables('createNewVNET'), createObject('privateDnsZoneGroupConfigs', createArray(createObject('privateDnsZoneResourceId', reference('dnsZoneDbw').outputs.resourceId.value))), null())]", + "tags": "[parameters('tags')]", + "enableTelemetry": "[parameters('enableTelemetry')]", + "lock": "[parameters('lock')]", + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), variables('ownerRoleAssignments'), createArray())]" + }, + { + "name": "[format('{0}-dbw-auth-pep', parameters('name'))]", + "location": "[parameters('location')]", + "service": "browser_authentication", + "subnetResourceId": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).subnetResourceIdPrivateLink]", + "privateDnsZoneGroup": "[if(variables('createNewVNET'), createObject('privateDnsZoneGroupConfigs', createArray(createObject('privateDnsZoneResourceId', reference('dnsZoneDbw').outputs.resourceId.value))), null())]", + "tags": "[parameters('tags')]", + "enableTelemetry": "[parameters('enableTelemetry')]", + "lock": "[parameters('lock')]", + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), variables('ownerRoleAssignments'), createArray())]" + } + ] + }, + "privateStorageAccount": { + "value": "Enabled" + }, + "publicNetworkAccess": "[if(empty(variables('dbwIpRules')), createObject('value', 'Disabled'), createObject('value', 'Enabled'))]", + "requiredNsgRules": "[if(empty(variables('dbwIpRules')), createObject('value', 'NoAzureDatabricksRules'), createObject('value', 'AllRules'))]", + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "skuName": { + "value": "premium" + }, + "storageAccountName": { + "value": null + }, + "storageAccountPrivateEndpoints": { + "value": [ + { + "name": "[format('{0}-sa-blob-pep', parameters('name'))]", + "location": "[parameters('location')]", + "service": "blob", + "subnetResourceId": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).subnetResourceIdPrivateLink]", + "privateDnsZoneGroup": "[if(variables('createNewVNET'), createObject('privateDnsZoneGroupConfigs', createArray(createObject('privateDnsZoneResourceId', reference('dnsZoneSaBlob').outputs.resourceId.value))), null())]", + "tags": "[parameters('tags')]", + "enableTelemetry": "[parameters('enableTelemetry')]", + "lock": "[parameters('lock')]", + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), variables('ownerRoleAssignments'), createArray())]" + } + ] + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "5134701226569732145" + }, + "name": "Azure Databricks Workspaces", + "description": "This module deploys an Azure Databricks Workspace.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "metadata": { + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." + } + } + } + }, + "nullable": true + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "nullable": true + }, + "customerManagedKeyManagedDiskType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + }, + "rotationToLatestKeyVersionEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicate whether the latest key version should be automatically used for Managed Disk Encryption. Enabled by default." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "defaultCatalogType": { + "type": "object", + "properties": { + "initialType": { + "type": "string", + "allowedValues": [ + "HiveMetastore", + "UnityCatalog" + ], + "metadata": { + "description": "Required. Choose between HiveMetastore or UnityCatalog." + } + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Azure Databricks workspace to create." + } + }, + "managedResourceGroupResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The managed resource group ID. It is created by the module as per the to-be resource ID you provide." + } + }, + "skuName": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "trial", + "standard", + "premium" + ], + "metadata": { + "description": "Optional. The pricing tier of workspace." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "customVirtualNetworkResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The resource ID of a Virtual Network where this Databricks Cluster should be created." + } + }, + "amlWorkspaceResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The resource ID of a Azure Machine Learning workspace to link with Databricks workspace." + } + }, + "customPrivateSubnetName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Private Subnet within the Virtual Network." + } + }, + "customPublicSubnetName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of a Public Subnet within the Virtual Network." + } + }, + "disablePublicIp": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Disable Public IP." + } + }, + "customerManagedKey": { + "$ref": "#/definitions/customerManagedKeyType", + "metadata": { + "description": "Optional. The customer managed key definition to use for the managed service." + } + }, + "customerManagedKeyManagedDisk": { + "$ref": "#/definitions/customerManagedKeyManagedDiskType", + "metadata": { + "description": "Optional. The customer managed key definition to use for the managed disk." + } + }, + "loadBalancerBackendPoolName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the outbound Load Balancer Backend Pool for Secure Cluster Connectivity (No Public IP)." + } + }, + "loadBalancerResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource URI of Outbound Load balancer for Secure Cluster Connectivity (No Public IP) workspace." + } + }, + "natGatewayName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the NAT gateway for Secure Cluster Connectivity (No Public IP) workspace subnets." + } + }, + "prepareEncryption": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Prepare the workspace for encryption. Enables the Managed Identity for managed storage account." + } + }, + "publicIpName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the Public IP for No Public IP workspace with managed vNet." + } + }, + "requireInfrastructureEncryption": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. A boolean indicating whether or not the DBFS root file system will be enabled with secondary layer of encryption with platform managed keys for data at rest." + } + }, + "storageAccountName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Default DBFS storage account name." + } + }, + "storageAccountSkuName": { + "type": "string", + "defaultValue": "Standard_GRS", + "metadata": { + "description": "Optional. Storage account SKU name." + } + }, + "vnetAddressPrefix": { + "type": "string", + "defaultValue": "10.139", + "metadata": { + "description": "Optional. Address prefix for Managed virtual network." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. The network access type for accessing workspace. Set value to disabled to access workspace only via private link." + } + }, + "requiredNsgRules": { + "type": "string", + "defaultValue": "AllRules", + "allowedValues": [ + "AllRules", + "NoAzureDatabricksRules" + ], + "metadata": { + "description": "Optional. Gets or sets a value indicating whether data plane (clusters) to control plane communication happen over private endpoint." + } + }, + "privateStorageAccount": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Enabled", + "Disabled", + "" + ], + "metadata": { + "description": "Optional. Determines whether the managed storage account should be private or public. For best security practices, it is recommended to set it to Enabled." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "storageAccountPrivateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints for the managed workspace storage account, required when privateStorageAccount is set to Enabled. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "accessConnectorResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. The resource ID of the associated access connector for private access to the managed workspace storage account. Required if privateStorageAccount is enabled." + } + }, + "defaultCatalog": { + "$ref": "#/definitions/defaultCatalogType", + "nullable": true, + "metadata": { + "description": "Optional. The default catalog configuration for the Databricks workspace." + } + }, + "automaticClusterUpdate": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Enabled", + "Disabled", + "" + ], + "metadata": { + "description": "Optional. The value for enabling automatic cluster updates in enhanced security compliance." + } + }, + "complianceStandards": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The compliance standards array for the security profile. Should be a list of compliance standards like \"HIPAA\", \"NONE\" or \"PCI_DSS\"." + } + }, + "complianceSecurityProfileValue": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Enabled", + "Disabled", + "" + ], + "metadata": { + "description": "Optional. The value to Enable or Disable for the compliance security profile." + } + }, + "enhancedSecurityMonitoring": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Enabled", + "Disabled", + "" + ], + "metadata": { + "description": "Optional. The value for enabling or configuring enhanced security monitoring." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "cMKKeyVault::cMKKey": { + "condition": "[and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), not(empty(tryGet(parameters('customerManagedKey'), 'keyName')))))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKey'), 'keyName'), 'dummyKey'))]", + "dependsOn": [ + "cMKKeyVault" + ] + }, + "cMKManagedDiskKeyVault::cMKKey": { + "condition": "[and(not(empty(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'))), and(not(empty(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'))), not(empty(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyName')))))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyName'), 'dummyKey'))]", + "dependsOn": [ + "cMKManagedDiskKeyVault" + ] + }, + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.databricks-workspace.{0}.{1}', replace('0.8.5', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "cMKKeyVault": { + "condition": "[not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId')))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2023-07-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/'))]" + }, + "cMKManagedDiskKeyVault": { + "condition": "[not(empty(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId')))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2023-07-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), 'dummyVault'), '/'))]" + }, + "workspace": { + "type": "Microsoft.Databricks/workspaces", + "apiVersion": "2024-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]" + }, + "properties": "[shallowMerge(createArray(createObject('managedResourceGroupId', if(not(empty(parameters('managedResourceGroupResourceId'))), parameters('managedResourceGroupResourceId'), format('{0}/resourceGroups/rg-{1}-managed', subscription().id, parameters('name'))), 'parameters', shallowMerge(createArray(createObject('enableNoPublicIp', createObject('value', parameters('disablePublicIp')), 'prepareEncryption', createObject('value', parameters('prepareEncryption')), 'vnetAddressPrefix', createObject('value', parameters('vnetAddressPrefix')), 'requireInfrastructureEncryption', createObject('value', parameters('requireInfrastructureEncryption'))), if(not(empty(parameters('customVirtualNetworkResourceId'))), createObject('customVirtualNetworkId', createObject('value', parameters('customVirtualNetworkResourceId'))), createObject()), if(not(empty(parameters('amlWorkspaceResourceId'))), createObject('amlWorkspaceId', createObject('value', parameters('amlWorkspaceResourceId'))), createObject()), if(not(empty(parameters('customPrivateSubnetName'))), createObject('customPrivateSubnetName', createObject('value', parameters('customPrivateSubnetName'))), createObject()), if(not(empty(parameters('customPublicSubnetName'))), createObject('customPublicSubnetName', createObject('value', parameters('customPublicSubnetName'))), createObject()), if(not(empty(parameters('loadBalancerBackendPoolName'))), createObject('loadBalancerBackendPoolName', createObject('value', parameters('loadBalancerBackendPoolName'))), createObject()), if(not(empty(parameters('loadBalancerResourceId'))), createObject('loadBalancerId', createObject('value', parameters('loadBalancerResourceId'))), createObject()), if(not(empty(parameters('natGatewayName'))), createObject('natGatewayName', createObject('value', parameters('natGatewayName'))), createObject()), if(not(empty(parameters('publicIpName'))), createObject('publicIpName', createObject('value', parameters('publicIpName'))), createObject()), if(not(empty(parameters('storageAccountName'))), createObject('storageAccountName', createObject('value', parameters('storageAccountName'))), createObject()), if(not(empty(parameters('storageAccountSkuName'))), createObject('storageAccountSkuName', createObject('value', parameters('storageAccountSkuName'))), createObject()))), 'publicNetworkAccess', parameters('publicNetworkAccess'), 'requiredNsgRules', parameters('requiredNsgRules'), 'encryption', if(or(not(empty(parameters('customerManagedKey'))), not(empty(parameters('customerManagedKeyManagedDisk')))), createObject('entities', createObject('managedServices', if(not(empty(parameters('customerManagedKey'))), createObject('keySource', 'Microsoft.Keyvault', 'keyVaultProperties', createObject('keyVaultUri', reference('cMKKeyVault').vaultUri, 'keyName', parameters('customerManagedKey').keyName, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKey'), 'keyVersion'), ''))), parameters('customerManagedKey').keyVersion, last(split(reference('cMKKeyVault::cMKKey').keyUriWithVersion, '/'))))), null()), 'managedDisk', if(not(empty(parameters('customerManagedKeyManagedDisk'))), createObject('keySource', 'Microsoft.Keyvault', 'keyVaultProperties', createObject('keyVaultUri', reference('cMKManagedDiskKeyVault').vaultUri, 'keyName', parameters('customerManagedKeyManagedDisk').keyName, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVersion'), ''))), parameters('customerManagedKeyManagedDisk').keyVersion, last(split(reference('cMKManagedDiskKeyVault::cMKKey').keyUriWithVersion, '/')))), 'rotationToLatestKeyVersionEnabled', coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'rotationToLatestKeyVersionEnabled'), true())), null()))), null())), if(not(empty(parameters('privateStorageAccount'))), createObject('defaultStorageFirewall', parameters('privateStorageAccount'), 'accessConnector', createObject('id', parameters('accessConnectorResourceId'), 'identityType', 'SystemAssigned')), createObject()), if(not(empty(parameters('defaultCatalog'))), createObject('defaultCatalog', createObject('initialName', '', 'initialType', tryGet(parameters('defaultCatalog'), 'initialType'))), createObject()), if(or(or(not(empty(parameters('automaticClusterUpdate'))), not(empty(parameters('complianceStandards')))), not(empty(parameters('enhancedSecurityMonitoring')))), createObject('enhancedSecurityCompliance', createObject('automaticClusterUpdate', createObject('value', parameters('automaticClusterUpdate')), 'complianceSecurityProfile', createObject('complianceStandards', parameters('complianceStandards'), 'value', parameters('complianceSecurityProfileValue')), 'enhancedSecurityMonitoring', createObject('value', parameters('enhancedSecurityMonitoring')))), createObject())))]", + "dependsOn": [ + "cMKKeyVault", + "cMKManagedDiskKeyVault" + ] + }, + "workspace_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Databricks/workspaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "workspace" + ] + }, + "workspace_diagnosticSettings": { + "copy": { + "name": "workspace_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Databricks/workspaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "workspace" + ] + }, + "workspace_roleAssignments": { + "copy": { + "name": "workspace_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Databricks/workspaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Databricks/workspaces', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "workspace" + ] + }, + "workspace_privateEndpoints": { + "copy": { + "name": "workspace_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-workspace-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'resourceGroupName'), '')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Databricks/workspaces', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Databricks/workspaces', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Databricks/workspaces', parameters('name')), 'groupIds', createArray(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Databricks/workspaces', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Databricks/workspaces', parameters('name')), 'groupIds', createArray(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroup": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1277254088602407590" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "5805178546717255803" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDnsZoneConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", + "input": { + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" + } + } + } + ] + }, + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" + } + } + } + }, + "dependsOn": [ + "workspace" + ] + }, + "storageAccount_storageAccountPrivateEndpoints": { + "copy": { + "name": "storageAccount_storageAccountPrivateEndpoints", + "count": "[length(coalesce(parameters('storageAccountPrivateEndpoints'), createArray()))]", + "mode": "serial", + "batchSize": 1 + }, + "condition": "[equals(parameters('privateStorageAccount'), 'Enabled')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-workspacestorage-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[coalesce(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'resourceGroupName'), '')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', reference('workspace').parameters.storageAccountName.value, coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()].service, copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', reference('workspace').parameters.storageAccountName.value, coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId(last(split(reference('workspace').managedResourceGroupId, '/')), 'microsoft.storage/storageAccounts', reference('workspace').parameters.storageAccountName.value), 'groupIds', createArray(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()].service))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', reference('workspace').parameters.storageAccountName.value, coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId(last(split(reference('workspace').managedResourceGroupId, '/')), 'microsoft.storage/storageAccounts', reference('workspace').parameters.storageAccountName.value), 'groupIds', createArray(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()].service), 'requestMessage', coalesce(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", + "subnetResourceId": { + "value": "[coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroup": { + "value": "[tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('storageAccountPrivateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1277254088602407590" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "5805178546717255803" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDnsZoneConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", + "input": { + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" + } + } + } + ] + }, + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" + } + } + } + }, + "dependsOn": [ + "workspace" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed databricks workspace." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed databricks workspace." + }, + "value": "[resourceId('Microsoft.Databricks/workspaces', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed databricks workspace." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('workspace', '2024-05-01', 'full').location]" + }, + "managedResourceGroupId": { + "type": "string", + "metadata": { + "description": "The resource ID of the managed resource group." + }, + "value": "[reference('workspace').managedResourceGroupId]" + }, + "managedResourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the managed resource group." + }, + "value": "[last(split(reference('workspace').managedResourceGroupId, '/'))]" + }, + "storageAccountName": { + "type": "string", + "metadata": { + "description": "The name of the DBFS storage account." + }, + "value": "[reference('workspace').parameters.storageAccountName.value]" + }, + "storageAccountId": { + "type": "string", + "metadata": { + "description": "The resource ID of the DBFS storage account." + }, + "value": "[resourceId(last(split(reference('workspace').managedResourceGroupId, '/')), 'microsoft.storage/storageAccounts', reference('workspace').parameters.storageAccountName.value)]" + }, + "workspaceUrl": { + "type": "string", + "metadata": { + "description": "The workspace URL which is of the format 'adb-{workspaceId}.{random}.azuredatabricks.net'." + }, + "value": "[reference('workspace').workspaceUrl]" + }, + "workspaceId": { + "type": "string", + "metadata": { + "description": "The unique identifier of the databricks workspace in databricks control plane." + }, + "value": "[reference('workspace').workspaceId]" + }, + "privateEndpoints": { + "type": "array", + "metadata": { + "description": "The private endpoints of the Databricks Workspace." + }, + "copy": { + "count": "[length(if(not(empty(parameters('privateEndpoints'))), array(parameters('privateEndpoints')), createArray()))]", + "input": { + "name": "[reference(format('workspace_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('workspace_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('workspace_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('workspace_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('workspace_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + } + } + }, + "storagePrivateEndpoints": { + "type": "array", + "metadata": { + "description": "The private endpoints of the Databricks Workspace Storage." + }, + "copy": { + "count": "[length(if(and(not(empty(parameters('storageAccountPrivateEndpoints'))), equals(parameters('privateStorageAccount'), 'Enabled')), array(parameters('storageAccountPrivateEndpoints')), createArray()))]", + "input": { + "name": "[reference(format('storageAccount_storageAccountPrivateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('storageAccount_storageAccountPrivateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('storageAccount_storageAccountPrivateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('storageAccount_storageAccountPrivateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('storageAccount_storageAccountPrivateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + } + } + } + } + } + }, + "dependsOn": [ + "accessConnector", + "dnsZoneDbw", + "dnsZoneSaBlob", + "log", + "logExisting", + "vnet", + "vnetExisting" + ] + }, + "dnsZoneDbw": { + "condition": "[and(variables('createNewVNET'), parameters('enableDatabricks'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-zone-{1}', uniqueString(deployment().name, parameters('location')), variables('privateDnsZoneNameDbw'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('privateDnsZoneNameDbw')]" + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "global" + }, + "roleAssignments": "[if(not(empty(variables('ownerRoleAssignments'))), createObject('value', variables('ownerRoleAssignments')), createObject('value', createArray()))]", + "lock": { + "value": "[parameters('lock')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "virtualNetworkLinks": { + "value": [ + { + "registrationEnabled": false, + "virtualNetworkResourceId": "[reference('vnet').outputs.resourceId.value]" + } + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "5518185016108244461" + }, + "name": "Private DNS Zones", + "description": "This module deploys a Private DNS zone.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "aType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "aRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipv4Address": { + "type": "string", + "metadata": { + "description": "Required. The IPv4 address of this A record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of A records in the record set." + } + } + } + }, + "nullable": true + }, + "aaaaType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "aaaaRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipv6Address": { + "type": "string", + "metadata": { + "description": "Required. The IPv6 address of this AAAA record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of AAAA records in the record set." + } + } + } + }, + "nullable": true + }, + "cnameType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "cnameRecord": { + "type": "object", + "properties": { + "cname": { + "type": "string", + "metadata": { + "description": "Required. The canonical name of the CNAME record." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The CNAME record in the record set." + } + } + } + }, + "nullable": true + }, + "mxType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "mxRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "exchange": { + "type": "string", + "metadata": { + "description": "Required. The domain name of the mail host for this MX record." + } + }, + "preference": { + "type": "int", + "metadata": { + "description": "Required. The preference value for this MX record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of MX records in the record set." + } + } + } + }, + "nullable": true + }, + "ptrType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "ptrRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ptrdname": { + "type": "string", + "metadata": { + "description": "Required. The PTR target domain name for this PTR record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of PTR records in the record set." + } + } + } + }, + "nullable": true + }, + "soaType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "soaRecord": { + "type": "object", + "properties": { + "email": { + "type": "string", + "metadata": { + "description": "Required. The email contact for this SOA record." + } + }, + "expireTime": { + "type": "int", + "metadata": { + "description": "Required. The expire time for this SOA record." + } + }, + "host": { + "type": "string", + "metadata": { + "description": "Required. The domain name of the authoritative name server for this SOA record." + } + }, + "minimumTtl": { + "type": "int", + "metadata": { + "description": "Required. The minimum value for this SOA record. By convention this is used to determine the negative caching duration." + } + }, + "refreshTime": { + "type": "int", + "metadata": { + "description": "Required. The refresh value for this SOA record." + } + }, + "retryTime": { + "type": "int", + "metadata": { + "description": "Required. The retry time for this SOA record." + } + }, + "serialNumber": { + "type": "int", + "metadata": { + "description": "Required. The serial number for this SOA record." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The SOA record in the record set." + } + } + } + }, + "nullable": true + }, + "srvType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "srvRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "priority": { + "type": "int", + "metadata": { + "description": "Required. The priority value for this SRV record." + } + }, + "weight": { + "type": "int", + "metadata": { + "description": "Required. The weight value for this SRV record." + } + }, + "port": { + "type": "int", + "metadata": { + "description": "Required. The port value for this SRV record." + } + }, + "target": { + "type": "string", + "metadata": { + "description": "Required. The target domain name for this SRV record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of SRV records in the record set." + } + } + } + }, + "nullable": true + }, + "txtType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "txtRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The text value of this TXT record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of TXT records in the record set." + } + } + } + }, + "nullable": true + }, + "virtualNetworkLinkType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 80, + "metadata": { + "description": "Optional. The resource name." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the virtual network to link." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Azure Region where the resource lives." + } + }, + "registrationEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Private DNS zone name." + } + }, + "a": { + "$ref": "#/definitions/aType", + "metadata": { + "description": "Optional. Array of A records." + } + }, + "aaaa": { + "$ref": "#/definitions/aaaaType", + "metadata": { + "description": "Optional. Array of AAAA records." + } + }, + "cname": { + "$ref": "#/definitions/cnameType", + "metadata": { + "description": "Optional. Array of CNAME records." + } + }, + "mx": { + "$ref": "#/definitions/mxType", + "metadata": { + "description": "Optional. Array of MX records." + } + }, + "ptr": { + "$ref": "#/definitions/ptrType", + "metadata": { + "description": "Optional. Array of PTR records." + } + }, + "soa": { + "$ref": "#/definitions/soaType", + "metadata": { + "description": "Optional. Array of SOA records." + } + }, + "srv": { + "$ref": "#/definitions/srvType", + "metadata": { + "description": "Optional. Array of SRV records." + } + }, + "txt": { + "$ref": "#/definitions/txtType", + "metadata": { + "description": "Optional. Array of TXT records." + } + }, + "virtualNetworkLinks": { + "$ref": "#/definitions/virtualNetworkLinkType", + "metadata": { + "description": "Optional. Array of custom objects describing vNet links of the DNS zone. Each object should contain properties 'virtualNetworkResourceId' 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." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. The location of the PrivateDNSZone. Should be global." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privatednszone.{0}.{1}', replace('0.6.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateDnsZone": { + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + "privateDnsZone_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_roleAssignments": { + "copy": { + "name": "privateDnsZone_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_A": { + "copy": { + "name": "privateDnsZone_A", + "count": "[length(coalesce(parameters('a'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-ARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('a'), createArray())[copyIndex()].name]" + }, + "aRecords": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'aRecords')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1641889417618452692" + }, + "name": "Private DNS Zone A record", + "description": "This module deploys a Private DNS Zone A record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the A record." + } + }, + "aRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of A records in the record set." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "A": { + "type": "Microsoft.Network/privateDnsZones/A", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "aRecords": "[parameters('aRecords')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "A_roleAssignments": { + "copy": { + "name": "A_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/A/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "A" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed A record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed A record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed A record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_AAAA": { + "copy": { + "name": "privateDnsZone_AAAA", + "count": "[length(coalesce(parameters('aaaa'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-AAAARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('aaaa'), createArray())[copyIndex()].name]" + }, + "aaaaRecords": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'aaaaRecords')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "17163414995652446126" + }, + "name": "Private DNS Zone AAAA record", + "description": "This module deploys a Private DNS Zone AAAA record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the AAAA record." + } + }, + "aaaaRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of AAAA records in the record set." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "AAAA": { + "type": "Microsoft.Network/privateDnsZones/AAAA", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "aaaaRecords": "[parameters('aaaaRecords')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "AAAA_roleAssignments": { + "copy": { + "name": "AAAA_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/AAAA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "AAAA" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed AAAA record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed AAAA record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed AAAA record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_CNAME": { + "copy": { + "name": "privateDnsZone_CNAME", + "count": "[length(coalesce(parameters('cname'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-CNAMERecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('cname'), createArray())[copyIndex()].name]" + }, + "cnameRecord": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'cnameRecord')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "2493714129104385633" + }, + "name": "Private DNS Zone CNAME record", + "description": "This module deploys a Private DNS Zone CNAME record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the CNAME record." + } + }, + "cnameRecord": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. A CNAME record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "CNAME": { + "type": "Microsoft.Network/privateDnsZones/CNAME", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "cnameRecord": "[parameters('cnameRecord')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "CNAME_roleAssignments": { + "copy": { + "name": "CNAME_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/CNAME/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "CNAME" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed CNAME record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed CNAME record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed CNAME record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_MX": { + "copy": { + "name": "privateDnsZone_MX", + "count": "[length(coalesce(parameters('mx'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-MXRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('mx'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'metadata')]" + }, + "mxRecords": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'mxRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "10928449924272756679" + }, + "name": "Private DNS Zone MX record", + "description": "This module deploys a Private DNS Zone MX record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the MX record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "mxRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of MX records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "MX": { + "type": "Microsoft.Network/privateDnsZones/MX", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "mxRecords": "[parameters('mxRecords')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "MX_roleAssignments": { + "copy": { + "name": "MX_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/MX/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "MX" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed MX record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed MX record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed MX record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_PTR": { + "copy": { + "name": "privateDnsZone_PTR", + "count": "[length(coalesce(parameters('ptr'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-PTRRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('ptr'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'metadata')]" + }, + "ptrRecords": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'ptrRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "13191587152357386110" + }, + "name": "Private DNS Zone PTR record", + "description": "This module deploys a Private DNS Zone PTR record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the PTR record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ptrRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of PTR records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "PTR": { + "type": "Microsoft.Network/privateDnsZones/PTR", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "ptrRecords": "[parameters('ptrRecords')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "PTR_roleAssignments": { + "copy": { + "name": "PTR_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/PTR/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "PTR" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed PTR record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed PTR record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed PTR record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_SOA": { + "copy": { + "name": "privateDnsZone_SOA", + "count": "[length(coalesce(parameters('soa'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-SOARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('soa'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'metadata')]" + }, + "soaRecord": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'soaRecord')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "12872700379964561295" + }, + "name": "Private DNS Zone SOA record", + "description": "This module deploys a Private DNS Zone SOA record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SOA record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "soaRecord": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. A SOA record." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "SOA": { + "type": "Microsoft.Network/privateDnsZones/SOA", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "soaRecord": "[parameters('soaRecord')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "SOA_roleAssignments": { + "copy": { + "name": "SOA_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SOA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "SOA" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed SOA record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed SOA record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed SOA record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_SRV": { + "copy": { + "name": "privateDnsZone_SRV", + "count": "[length(coalesce(parameters('srv'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-SRVRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('srv'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'metadata')]" + }, + "srvRecords": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'srvRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "12918383495773487180" + }, + "name": "Private DNS Zone SRV record", + "description": "This module deploys a Private DNS Zone SRV record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SRV record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "srvRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of SRV records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "SRV": { + "type": "Microsoft.Network/privateDnsZones/SRV", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "srvRecords": "[parameters('srvRecords')]", + "ttl": "[parameters('ttl')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "SRV_roleAssignments": { + "copy": { + "name": "SRV_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SRV/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "SRV" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed SRV record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed SRV record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed SRV record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_TXT": { + "copy": { + "name": "privateDnsZone_TXT", + "count": "[length(coalesce(parameters('txt'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-TXTRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('txt'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'metadata')]" + }, + "txtRecords": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'txtRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "128006490354221158" + }, + "name": "Private DNS Zone TXT record", + "description": "This module deploys a Private DNS Zone TXT record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the TXT record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "txtRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of TXT records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "TXT": { + "type": "Microsoft.Network/privateDnsZones/TXT", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]", + "txtRecords": "[parameters('txtRecords')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "TXT_roleAssignments": { + "copy": { + "name": "TXT_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/TXT/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "TXT" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed TXT record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed TXT record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed TXT record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_virtualNetworkLinks": { + "copy": { + "name": "privateDnsZone_virtualNetworkLinks", + "count": "[length(coalesce(parameters('virtualNetworkLinks'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-VirtualNetworkLink-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'name'), format('{0}-vnetlink', last(split(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()].virtualNetworkResourceId, '/'))))]" + }, + "virtualNetworkResourceId": { + "value": "[coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()].virtualNetworkResourceId]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'location'), 'global')]" + }, + "registrationEnabled": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'registrationEnabled'), false())]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1713449351614683457" + }, + "name": "Private DNS Zone Virtual Network Link", + "description": "This module deploys a Private DNS Zone Virtual Network Link.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "[format('{0}-vnetlink', last(split(parameters('virtualNetworkResourceId'), '/')))]", + "metadata": { + "description": "Optional. The name of the virtual network link." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. The location of the PrivateDNSZone. Should be global." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "registrationEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "Required. Link to another virtual network resource ID." + } + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "virtualNetworkLink": { + "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "registrationEnabled": "[parameters('registrationEnabled')]", + "virtualNetwork": { + "id": "[parameters('virtualNetworkResourceId')]" + } + }, + "dependsOn": [ + "privateDnsZone" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed virtual network link." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed virtual network link." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/virtualNetworkLinks', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed virtual network link." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('virtualNetworkLink', '2020-06-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private DNS zone was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private DNS zone." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private DNS zone." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones', parameters('name'))]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateDnsZone', '2020-06-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vnet" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the resource." + }, + "value": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).resourceId]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the resource." + }, + "value": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).location]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the managed resource group." + }, + "value": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).resourceGroupName]" + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Azure Virtual Network." + }, + "value": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).resourceId]" + }, + "virtualNetworkName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Virtual Network." + }, + "value": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).name]" + }, + "virtualNetworkLocation": { + "type": "string", + "metadata": { + "description": "The location of the Azure Virtual Network." + }, + "value": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).location]" + }, + "virtualNetworkResourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Virtual Network resource group." + }, + "value": "[createObject('resourceId', if(variables('createNewVNET'), reference('vnet').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))))), 'name', if(variables('createNewVNET'), reference('vnet').outputs.name.value, if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), 'location', if(variables('createNewVNET'), reference('vnet').outputs.location.value, reference('vnetExisting', '2023-11-01', 'full').location), 'resourceGroupName', if(variables('createNewVNET'), reference('vnet').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/')))), '/')[4]), 'subnetResourceIdPrivateLink', if(variables('createNewVNET'), reference('vnet').outputs.subnetResourceIds.value[0], extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewVNET'), subscription().id, split(parameters('virtualNetworkResourceId'), '/')[2]), if(variables('createNewVNET'), resourceGroup().id, split(parameters('virtualNetworkResourceId'), '/')[4])), 'Microsoft.Network/virtualNetworks/subnets', if(variables('createNewVNET'), 'dummyName', last(split(parameters('virtualNetworkResourceId'), '/'))), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'virtualNetwork'), 'subnetNamePrivateLink'), 'dummyName'))), 'subnetNameDbwFrontend', if(variables('createNewVNET'), variables('subnetNameDbwFrontend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameFrontend'), 'dummyName')), 'subnetNameDbwBackend', if(variables('createNewVNET'), variables('subnetNameDbwBackend'), coalesce(tryGet(tryGet(parameters('advancedOptions'), 'databricks'), 'subnetNameBackend'), 'dummyName'))).resourceGroupName]" + }, + "logAnalyticsWorkspaceResourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Azure Log Analytics Workspace." + }, + "value": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).resourceId]" + }, + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Log Analytics Workspace." + }, + "value": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).name]" + }, + "logAnalyticsWorkspaceLocation": { + "type": "string", + "metadata": { + "description": "The location of the Azure Log Analytics Workspace." + }, + "value": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).location]" + }, + "logAnalyticsWorkspaceResourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Log Analytics Workspace resource group." + }, + "value": "[createObject('resourceId', if(variables('createNewLog'), reference('log').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/'))))), 'name', if(variables('createNewLog'), reference('log').outputs.name.value, if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), 'location', if(variables('createNewLog'), reference('log').outputs.location.value, reference('logExisting', '2022-10-01', 'full').location), 'resourceGroupName', if(variables('createNewLog'), reference('log').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewLog'), subscription().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[2]), if(variables('createNewLog'), resourceGroup().id, split(parameters('logAnalyticsWorkspaceResourceId'), '/')[4])), 'Microsoft.OperationalInsights/workspaces', if(variables('createNewLog'), 'dummyName', last(split(parameters('logAnalyticsWorkspaceResourceId'), '/')))), '/')[4])).resourceGroupName]" + }, + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Azure Key Vault." + }, + "value": "[createObject('resourceId', if(variables('createNewKV'), reference('kv').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewKV'), subscription().id, split(parameters('keyVaultResourceId'), '/')[2]), if(variables('createNewKV'), resourceGroup().id, split(parameters('keyVaultResourceId'), '/')[4])), 'Microsoft.KeyVault/vaults', if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/'))))), 'name', if(variables('createNewKV'), reference('kv').outputs.name.value, if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/')))), 'location', if(variables('createNewKV'), reference('kv').outputs.location.value, reference('kvExisting', '2023-07-01', 'full').location), 'resourceGroupName', if(variables('createNewKV'), reference('kv').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewKV'), subscription().id, split(parameters('keyVaultResourceId'), '/')[2]), if(variables('createNewKV'), resourceGroup().id, split(parameters('keyVaultResourceId'), '/')[4])), 'Microsoft.KeyVault/vaults', if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/')))), '/')[4])).resourceId]" + }, + "keyVaultName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Key Vault." + }, + "value": "[createObject('resourceId', if(variables('createNewKV'), reference('kv').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewKV'), subscription().id, split(parameters('keyVaultResourceId'), '/')[2]), if(variables('createNewKV'), resourceGroup().id, split(parameters('keyVaultResourceId'), '/')[4])), 'Microsoft.KeyVault/vaults', if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/'))))), 'name', if(variables('createNewKV'), reference('kv').outputs.name.value, if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/')))), 'location', if(variables('createNewKV'), reference('kv').outputs.location.value, reference('kvExisting', '2023-07-01', 'full').location), 'resourceGroupName', if(variables('createNewKV'), reference('kv').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewKV'), subscription().id, split(parameters('keyVaultResourceId'), '/')[2]), if(variables('createNewKV'), resourceGroup().id, split(parameters('keyVaultResourceId'), '/')[4])), 'Microsoft.KeyVault/vaults', if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/')))), '/')[4])).name]" + }, + "keyVaultLocation": { + "type": "string", + "metadata": { + "description": "The location of the Azure Key Vault." + }, + "value": "[createObject('resourceId', if(variables('createNewKV'), reference('kv').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewKV'), subscription().id, split(parameters('keyVaultResourceId'), '/')[2]), if(variables('createNewKV'), resourceGroup().id, split(parameters('keyVaultResourceId'), '/')[4])), 'Microsoft.KeyVault/vaults', if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/'))))), 'name', if(variables('createNewKV'), reference('kv').outputs.name.value, if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/')))), 'location', if(variables('createNewKV'), reference('kv').outputs.location.value, reference('kvExisting', '2023-07-01', 'full').location), 'resourceGroupName', if(variables('createNewKV'), reference('kv').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewKV'), subscription().id, split(parameters('keyVaultResourceId'), '/')[2]), if(variables('createNewKV'), resourceGroup().id, split(parameters('keyVaultResourceId'), '/')[4])), 'Microsoft.KeyVault/vaults', if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/')))), '/')[4])).location]" + }, + "keyVaultResourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Key Vault resource group." + }, + "value": "[createObject('resourceId', if(variables('createNewKV'), reference('kv').outputs.resourceId.value, extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewKV'), subscription().id, split(parameters('keyVaultResourceId'), '/')[2]), if(variables('createNewKV'), resourceGroup().id, split(parameters('keyVaultResourceId'), '/')[4])), 'Microsoft.KeyVault/vaults', if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/'))))), 'name', if(variables('createNewKV'), reference('kv').outputs.name.value, if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/')))), 'location', if(variables('createNewKV'), reference('kv').outputs.location.value, reference('kvExisting', '2023-07-01', 'full').location), 'resourceGroupName', if(variables('createNewKV'), reference('kv').outputs.resourceGroupName.value, split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', if(variables('createNewKV'), subscription().id, split(parameters('keyVaultResourceId'), '/')[2]), if(variables('createNewKV'), resourceGroup().id, split(parameters('keyVaultResourceId'), '/')[4])), 'Microsoft.KeyVault/vaults', if(variables('createNewKV'), 'dummyName', last(split(parameters('keyVaultResourceId'), '/')))), '/')[4])).resourceGroupName]" + }, + "databricksResourceId": { + "type": "string", + "metadata": { + "description": "Conditional. The resource ID of the Azure Databricks when `enableDatabricks` is `true`." + }, + "value": "[if(parameters('enableDatabricks'), reference('dbw').outputs.resourceId.value, '')]" + }, + "databricksName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the Azure Databricks when `enableDatabricks` is `true`." + }, + "value": "[if(parameters('enableDatabricks'), reference('dbw').outputs.name.value, '')]" + }, + "databricksLocation": { + "type": "string", + "metadata": { + "description": "Conditional. The location of the Azure Databricks when `enableDatabricks` is `true`." + }, + "value": "[if(parameters('enableDatabricks'), reference('dbw').outputs.location.value, '')]" + }, + "databricksResourceGroupName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the Azure Databricks resource group when `enableDatabricks` is `true`." + }, + "value": "[if(parameters('enableDatabricks'), reference('dbw').outputs.resourceGroupName.value, '')]" + } + } +} \ No newline at end of file diff --git a/avm/ptn/data/private-analytical-workspace/tests/common.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/common.tests.ps1 new file mode 100644 index 0000000000..024d98b5e7 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/common.tests.ps1 @@ -0,0 +1,393 @@ +function Test-VerifyLock($ResourceId) { + # TODO: Not Implemented Yet - How to test it? +} + +function Test-VerifyRoleAssignment($ResourceId) { + # TODO: Not Implemented Yet - How to test it? +} + +function Test-VerifyOutputVariables($MustBeNullOrEmpty, $ResourceId, $Name, $Location, $ResourceGroupName) { + + if ( $MustBeNullOrEmpty -eq $true ) { + $ResourceId | Should -BeNullOrEmpty + $Name | Should -BeNullOrEmpty + $Location | Should -BeNullOrEmpty + $ResourceGroupName | Should -BeNullOrEmpty + } else { + $ResourceId | Should -Not -BeNullOrEmpty + $Name | Should -Not -BeNullOrEmpty + $Location | Should -Not -BeNullOrEmpty + $ResourceGroupName | Should -Not -BeNullOrEmpty + + $r = Get-AzResource -ResourceId $ResourceId + $r | Should -Not -BeNullOrEmpty + $r.Name | Should -Be $Name + $r.Location | Should -Be $Location + $r.ResourceGroupName | Should -Be $ResourceGroupName + } +} + +function Test-VerifyTagsForResource($ResourceId, $Tags) { + $t = Get-AzTag -ResourceId $ResourceId + $t | Should -Not -BeNullOrEmpty + foreach ($key in $Tags.Keys) { + $t.Properties.TagsProperty[$key] | Should -Be $Tags[$key] + } +} + +function Test-VerifyDiagSettings($ResourceId, $LogAnalyticsWorkspaceResourceId, $Logs) { + $diag = Get-AzDiagnosticSetting -ResourceId $ResourceId -Name avm-diagnostic-settings + $diag | Should -Not -BeNullOrEmpty + #$diag.ProvisioningState | Should -Be "Succeeded" # Not available in the output + $diag.Type | Should -Be 'Microsoft.Insights/diagnosticSettings' + $diag.WorkspaceId | Should -Be $LogAnalyticsWorkspaceResourceId + + $diagCat = Get-AzDiagnosticSettingCategory -ResourceId $ResourceId + $diagCat | Should -Not -BeNullOrEmpty + #$diagCat.ProvisioningState | Should -Be "Succeeded" # Not available in the output + $diagCat.Count | Should -Be $Logs.Count + for ($i = 0; $i -lt $diagCat.Count; $i++) { $diagCat[$i].Name | Should -BeIn $Logs } +} + +function Test-VerifyVirtualNetwork($VirtualNetworkResourceGroupName, $VirtualNetworkName, $Tags, $LogAnalyticsWorkspaceResourceId, $AddressPrefix, $NumberOfSubnets) { + $vnet = Get-AzVirtualNetwork -ResourceGroupName $VirtualNetworkResourceGroupName -Name $VirtualNetworkName + $vnet | Should -Not -BeNullOrEmpty + $vnet.ProvisioningState | Should -Be 'Succeeded' + $vnet.AddressSpace.Count | Should -Be 1 + $vnet.AddressSpace[0].AddressPrefixes.Count | Should -Be 1 + $vnet.AddressSpace[0].AddressPrefixes[0] | Should -Be $AddressPrefix + $vnet.EnableDdosProtection | Should -Be $false + $vnet.VirtualNetworkPeerings.Count | Should -Be 0 + $vnet.Subnets.Count | Should -Be $NumberOfSubnets + $vnet.IpAllocations.Count | Should -Be 0 + $vnet.DhcpOptions.DnsServers | Should -BeNullOrEmpty + $vnet.FlowTimeoutInMinutes | Should -BeNullOrEmpty + $vnet.BgpCommunities | Should -BeNullOrEmpty + $vnet.Encryption | Should -BeNullOrEmpty + $vnet.DdosProtectionPlan | Should -BeNullOrEmpty + $vnet.ExtendedLocation | Should -BeNullOrEmpty + + Test-VerifyTagsForResource -ResourceId $vnet.Id -Tags $Tags + + $logs = @('VMProtectionAlerts', 'AllMetrics') + Test-VerifyDiagSettings -ResourceId $vnet.Id -LogAnalyticsWorkspaceResourceId $LogAnalyticsWorkspaceResourceId -Logs $logs + + Test-VerifyLock -ResourceId $vnet.Id + Test-VerifyRoleAssignment -ResourceId $vnet.Id + + return $vnet +} + +function Test-VerifySubnet($Subnet, $SubnetName, $SubnetAddressPrefix, $NumberOfSecurityGroups, $NumberOfPrivateEndpoints, $NumberOfIpConfigurations, $DelegationServiceName) { + $Subnet.ProvisioningState | Should -Be 'Succeeded' + $Subnet.Name | Should -Be $SubnetName + $Subnet.PrivateEndpointNetworkPolicies | Should -Be 'Disabled' + $Subnet.PrivateLinkServiceNetworkPolicies | Should -Be 'Enabled' + $Subnet.AddressPrefix.Count | Should -Be 1 + $Subnet.AddressPrefix[0] | Should -Be $SubnetAddressPrefix + $Subnet.NetworkSecurityGroup.Count | Should -Be $NumberOfSecurityGroups + + if ( $null -eq $NumberOfPrivateEndpoints ) { $Subnet.PrivateEndpoints | Should -BeNullOrEmpty } + else { $Subnet.PrivateEndpoints.Count | Should -Be $NumberOfPrivateEndpoints } + + if ( $null -eq $NumberOfIpConfigurations ) { $Subnet.IpConfigurations | Should -BeNullOrEmpty } + else { $Subnet.IpConfigurations.Count | Should -Be $NumberOfIpConfigurations } + + $Subnet.ServiceAssociationLinks | Should -BeNullOrEmpty + $Subnet.ResourceNavigationLinks | Should -BeNullOrEmpty + $Subnet.ServiceEndpoints | Should -BeNullOrEmpty + $Subnet.ServiceEndpointPolicies | Should -BeNullOrEmpty + + if ( $null -eq $DelegationServiceName ) { $Subnet.Delegations | Should -BeNullOrEmpty } + else { + $Subnet.Delegations.Count | Should -Be 1 + $Subnet.Delegations[0].ProvisioningState | Should -Be 'Succeeded' + $Subnet.Delegations[0].ServiceName | Should -Be $DelegationServiceName + } + + $Subnet.IpAllocations | Should -BeNullOrEmpty + $Subnet.RouteTable | Should -BeNullOrEmpty + $Subnet.NatGateway | Should -BeNullOrEmpty + $Subnet.DefaultOutboundAccess | Should -BeNullOrEmpty + + return $Subnet +} + +function Test-VerifyNetworkSecurityGroup($NetworkSecurityGroupResourceId, $Tags, $VirtualNetworkResourceId, $SubnetName, $NumberOfSecurityRules, $NumberOfDefaultSecurityRules, $LogAnalyticsWorkspaceResourceId, $Logs) { + # TODO: Do we have to check for specific rules? + $nsg = Get-AzResource -ResourceId $NetworkSecurityGroupResourceId | Get-AzNetworkSecurityGroup + $nsg | Should -Not -BeNullOrEmpty + $nsg.ProvisioningState | Should -Be 'Succeeded' + $nsg.FlushConnection | Should -Be $false + $nsg.NetworkInterfaces | Should -BeNullOrEmpty + $nsg.SecurityRules.Count | Should -Be $NumberOfSecurityRules + $nsg.DefaultSecurityRules.Count | Should -Be $NumberOfDefaultSecurityRules + $nsg.Subnets.Count | Should -Be 1 + $nsg.Subnets[0].Id | Should -Be "$($VirtualNetworkResourceId)/subnets/$($SubnetName)" + + Test-VerifyTagsForResource -ResourceId $NetworkSecurityGroupResourceId -Tags $Tags + Test-VerifyDiagSettings -ResourceId $NetworkSecurityGroupResourceId -LogAnalyticsWorkspaceResourceId $LogAnalyticsWorkspaceResourceId -Logs $Logs + + Test-VerifyLock -ResourceId $NetworkSecurityGroupResourceId + Test-VerifyRoleAssignment -ResourceId $NetworkSecurityGroupResourceId + + return $nsg +} + +function Test-VerifyDnsZone($Name, $ResourceGroupName, $Tags, $NumberOfRecordSets) { + $z = Get-AzPrivateDnsZone -ResourceGroupName $ResourceGroupName -Name $Name + $z | Should -Not -BeNullOrEmpty + #$z.ProvisioningState | Should -Be "Succeeded" # Not available in the output + $z.NumberOfRecordSets | Should -Be $NumberOfRecordSets + $z.NumberOfVirtualNetworkLinks | Should -Be 1 + + Test-VerifyTagsForResource -ResourceId $z.ResourceId -Tags $Tags + + Test-VerifyLock -ResourceId $z.ResourceId + Test-VerifyRoleAssignment -ResourceId $z.ResourceId + + return $z +} + +function Test-VerifyPrivateEndpoint($Name, $ResourceGroupName, $Tags, $SubnetName, $ServiceId, $GroupId) { + $pep = Get-AzPrivateEndpoint -ResourceGroupName $ResourceGroupName -Name $Name + $pep | Should -Not -BeNullOrEmpty + $pep.ProvisioningState | Should -Be 'Succeeded' + $pep.Subnet.Id | Should -Be "$($virtualNetworkResourceId)/subnets/$($SubnetName)" + $pep.NetworkInterfaces.Count | Should -Be 1 + $pep.PrivateLinkServiceConnections.ProvisioningState | Should -Be 'Succeeded' + + if ( $null -eq $ServiceId ) { + # For some services I have no Id - but must be no empty + $pep.PrivateLinkServiceConnections.PrivateLinkServiceId | Should -Not -BeNullOrEmpty + } else { + $pep.PrivateLinkServiceConnections.PrivateLinkServiceId | Should -Be $ServiceId + } + + $pep.PrivateLinkServiceConnections.GroupIds.Count | Should -Be 1 + $pep.PrivateLinkServiceConnections.GroupIds | Should -Be $GroupId + $pep.PrivateLinkServiceConnections.PrivateLinkServiceConnectionState.Status | Should -Be 'Approved' + + Test-VerifyTagsForResource -ResourceId $pep.Id -Tags $Tags + + Test-VerifyLock -ResourceId $pep.Id + Test-VerifyRoleAssignment -ResourceId $pep.Id + + return $pep +} + +function Test-VerifyLogAnalyticsWorkspace($LogAnalyticsWorkspaceResourceGroupName, $LogAnalyticsWorkspaceName, $Tags, $Sku, $RetentionInDays, $DailyQuotaGb) { + $log = Get-AzOperationalInsightsWorkspace -ResourceGroupName $LogAnalyticsWorkspaceResourceGroupName -Name $LogAnalyticsWorkspaceName + $log | Should -Not -BeNullOrEmpty + $log.ProvisioningState | Should -Be 'Succeeded' + $log.Sku | Should -Be $Sku + $log.RetentionInDays | Should -Be $RetentionInDays + $log.WorkspaceCapping.DailyQuotaGb | Should -Be $DailyQuotaGb + $log.WorkspaceCapping.DataIngestionStatus | Should -Be 'RespectQuota' + $log.CapacityReservationLevel | Should -BeNullOrEmpty + $log.PublicNetworkAccessForIngestion | Should -Be 'Enabled' + $log.PublicNetworkAccessForQuery | Should -Be 'Enabled' + $log.ForceCmkForQuery | Should -Be $true + $log.PrivateLinkScopedResources | Should -BeNullOrEmpty + $log.DefaultDataCollectionRuleResourceId | Should -BeNullOrEmpty + $log.WorkspaceFeatures.EnableLogAccessUsingOnlyResourcePermissions | Should -Be $false + + Test-VerifyTagsForResource -ResourceId $log.ResourceId -Tags $Tags + + # No DIAG for LAW itself + + Test-VerifyLock -ResourceId $log.ResourceId + Test-VerifyRoleAssignment -ResourceId $log.ResourceId + + return $log +} + +function Test-VerifyKeyVault($KeyVaultResourceGroupName, $KeyVaultName, $Tags, $LogAnalyticsWorkspaceResourceId, $Sku, $EnableSoftDelete, $RetentionInDays, $PEPName, $NumberOfRecordSets, $SubnetName, $PublicNetworkAccess, $IpAddressRanges) { + $kv = Get-AzKeyVault -ResourceGroupName $KeyVaultResourceGroupName -VaultName $KeyVaultName + $kv | Should -Not -BeNullOrEmpty + #$kv.ProvisioningState | Should -Be "Succeeded" # Not available in the output + $kv.Sku | Should -Be $Sku + $kv.EnabledForDeployment | Should -Be $false + $kv.EnabledForTemplateDeployment | Should -Be $false + $kv.EnabledForDiskEncryption | Should -Be $false + $kv.EnableRbacAuthorization | Should -Be $true + $kv.EnableSoftDelete | Should -Be $EnableSoftDelete + $kv.SoftDeleteRetentionInDays | Should -Be $RetentionInDays + $kv.EnablePurgeProtection | Should -BeIn @($false, $null) + $kv.PublicNetworkAccess | Should -Be $PublicNetworkAccess + $kv.AccessPolicies | Should -BeNullOrEmpty + $kv.NetworkAcls.DefaultAction | Should -Be 'Deny' + $kv.NetworkAcls.Bypass | Should -Be 'None' + if ( $null -eq $IpAddressRanges ) { $kv.NetworkAcls.IpAddressRanges | Should -BeNullOrEmpty } + else { + $kv.NetworkAcls.IpAddressRanges.Count | Should -Be $IpAddressRanges.Count + + foreach ($ip in $IpAddressRanges) { + $kv.NetworkAcls.IpAddressRanges[$IpAddressRanges.IndexOf($ip)] | Should -Be $ip + } + } + + $kv.NetworkAcls.VirtualNetworkResourceIds | Should -BeNullOrEmpty + + Test-VerifyTagsForResource -ResourceId $kv.ResourceId -Tags $Tags + + $logs = @('AuditEvent', 'AzurePolicyEvaluationDetails', 'AllMetrics') + Test-VerifyDiagSettings -ResourceId $kv.ResourceId -LogAnalyticsWorkspaceResourceId $LogAnalyticsWorkspaceResourceId -Logs $logs + + Test-VerifyPrivateEndpoint -Name "$($kv.VaultName)$($PEPName)" -ResourceGroupName $KeyVaultResourceGroupName -Tags $Tags -SubnetName $SubnetName -ServiceId $kv.ResourceId -GroupId 'vault' + + if ( $NumberOfRecordSets -ne 0 ) { + Test-VerifyDnsZone -Name 'privatelink.vaultcore.azure.net' -ResourceGroupName $KeyVaultResourceGroupName -Tags $Tags -NumberOfRecordSets $NumberOfRecordSets + } + + Test-VerifyLock -ResourceId $kv.ResourceId + Test-VerifyRoleAssignment -ResourceId $kv.ResourceId + + return $kv +} + +function Test-VerifyDatabricksAccessConnector($DatabricksAcCResourceGroupName, $DatabricksAcCName, $Tags, $DatabricksResourceId) { + $acc = Get-AzDatabricksAccessConnector -ResourceGroupName $DatabricksAcCResourceGroupName -Name $DatabricksAcCName + $acc | Should -Not -BeNullOrEmpty + $acc.ProvisioningState | Should -Be 'Succeeded' + $acc.IdentityType | Should -Be 'SystemAssigned' + $acc.IdentityUserAssignedIdentity | ConvertFrom-Json | Should -BeNullOrEmpty + $acc.ReferedBy | Should -Be $DatabricksResourceId + + Test-VerifyTagsForResource -ResourceId $acc.Id -Tags $Tags + + # No DIAG for Access Connector itself + + Test-VerifyLock -ResourceId $acc.Id + Test-VerifyRoleAssignment -ResourceId $acc.Id + + return $acc +} + +function Test-VerifyDatabricks($DatabricksResourceGroupName, $DatabricksName, $Tags, $LogAnalyticsWorkspaceResourceId, $Sku, $VirtualNetworkResourceId, $PrivateSubnetName, $PublicSubnetName, $PEPName0, $PEPName1, $PEPName2, $BlobNumberOfRecordSets, $DatabricksNumberOfRecordSets, $PLSubnetName, $PublicNetworkAccess, $RequiredNsgRule) { + $adb = Get-AzDatabricksWorkspace -ResourceGroupName $DatabricksResourceGroupName -Name $DatabricksName + $adb | Should -Not -BeNullOrEmpty + $adb.ProvisioningState | Should -Be 'Succeeded' + $adb.AccessConnectorId | Should -Not -BeNullOrEmpty + $adb.AccessConnectorIdentityType | Should -Be 'SystemAssigned' + $adb.AccessConnectorUserAssignedIdentityId | Should -BeNullOrEmpty + $adb.AmlWorkspaceIdType | Should -BeNullOrEmpty + $adb.AmlWorkspaceIdValue | Should -BeNullOrEmpty + #Skip $adb.Authorization + $adb.AutomaticClusterUpdateValue | Should -BeNullOrEmpty + $adb.ComplianceSecurityProfileComplianceStandard | Should -BeNullOrEmpty + $adb.ComplianceSecurityProfileValue | Should -BeNullOrEmpty + #Skip $adb.CreatedByApplicationId, $adb.CreatedByOid, $adb.CreatedByPuid, $adb.CreatedDateTime, + $adb.CustomPrivateSubnetNameType | Should -Be 'String' + $adb.CustomPrivateSubnetNameValue | Should -Be $PrivateSubnetName + $adb.CustomPublicSubnetNameType | Should -Be 'String' + $adb.CustomPublicSubnetNameValue | Should -Be $PublicSubnetName + $adb.CustomVirtualNetworkIdType | Should -Be 'String' + $adb.CustomVirtualNetworkIdValue | Should -Be $VirtualNetworkResourceId + $adb.DefaultCatalogInitialName | Should -BeNullOrEmpty + $adb.DefaultCatalogInitialType | Should -BeNullOrEmpty + $adb.DefaultStorageFirewall | Should -Be 'Enabled' + $adb.DiskEncryptionSetId | Should -BeNullOrEmpty + $adb.EnableNoPublicIP | Should -Be $true + $adb.EnableNoPublicIPType | Should -Be 'Bool' + $adb.EncryptionKeyName | Should -BeNullOrEmpty + $adb.EncryptionKeySource | Should -BeNullOrEmpty + $adb.EncryptionKeyVaultUri | Should -BeNullOrEmpty + $adb.EncryptionKeyVersion | Should -BeNullOrEmpty + $adb.EncryptionType | Should -BeNullOrEmpty + $adb.EnhancedSecurityMonitoringValue | Should -BeNullOrEmpty + #Skip $adb.Id | Should -Be $databricksResourceId + $adb.IsUcEnabled | Should -Be $true + $adb.LoadBalancerBackendPoolNameType | Should -BeNullOrEmpty + $adb.LoadBalancerBackendPoolNameValue | Should -BeNullOrEmpty + $adb.LoadBalancerIdType | Should -BeNullOrEmpty + $adb.LoadBalancerIdValue | Should -BeNullOrEmpty + #Skip $adb.Location | Should -Be $databricksLocation + $adb.ManagedDiskIdentityPrincipalId | Should -BeNullOrEmpty + $adb.ManagedDiskIdentityTenantId | Should -BeNullOrEmpty + $adb.ManagedDiskIdentityType | Should -BeNullOrEmpty + $adb.ManagedDiskKeySource | Should -Be 'Microsoft.Keyvault' + $adb.ManagedDiskKeyVaultPropertiesKeyName | Should -BeNullOrEmpty + $adb.ManagedDiskKeyVaultPropertiesKeyVaultUri | Should -BeNullOrEmpty + $adb.ManagedDiskKeyVaultPropertiesKeyVersion | Should -BeNullOrEmpty + $adb.ManagedDiskRotationToLatestKeyVersionEnabled | Should -BeNullOrEmpty + #Skip $adb.ManagedResourceGroupId + $adb.ManagedServiceKeySource | Should -Be 'Microsoft.Keyvault' + $adb.ManagedServicesKeyVaultPropertiesKeyName | Should -BeNullOrEmpty + $adb.ManagedServicesKeyVaultPropertiesKeyVaultUri | Should -BeNullOrEmpty + $adb.ManagedServicesKeyVaultPropertiesKeyVersion | Should -BeNullOrEmpty + $adb.Name | Should -Be $DatabricksName + $adb.NatGatewayNameType | Should -BeNullOrEmpty + $adb.NatGatewayNameValue | Should -BeNullOrEmpty + $adb.PrepareEncryption | Should -Be $true + $adb.PrepareEncryptionType | Should -Be 'Bool' + + $adb.PrivateEndpointConnection.Count | Should -Be 2 + + $adb.PrivateEndpointConnection[0].GroupId.Count | Should -Be 1 + $adb.PrivateEndpointConnection[0].GroupId[0] | Should -Be 'databricks_ui_api' + $adb.PrivateEndpointConnection[0].PrivateLinkServiceConnectionStateStatus | Should -Be 'Approved' + $adb.PrivateEndpointConnection[0].ProvisioningState | Should -Be 'Succeeded' + + $adb.PrivateEndpointConnection[1].GroupId.Count | Should -Be 1 + $adb.PrivateEndpointConnection[1].GroupId[0] | Should -Be 'browser_authentication' + $adb.PrivateEndpointConnection[1].PrivateLinkServiceConnectionStateStatus | Should -Be 'Approved' + $adb.PrivateEndpointConnection[1].ProvisioningState | Should -Be 'Succeeded' + + $adb.PublicIPNameType | Should -Be 'String' + $adb.PublicIPNameValue | Should -Be 'nat-gw-public-ip' + $adb.PublicNetworkAccess | Should -Be $PublicNetworkAccess + $adb.RequireInfrastructureEncryption | Should -Be $false + $adb.RequireInfrastructureEncryptionType | Should -Be 'Bool' + $adb.RequiredNsgRule | Should -Be $RequiredNsgRule + $adb.ResourceGroupName | Should -Be $DatabricksResourceGroupName + #Skip $adb.ResourceTagType, $adb.ResourceTagValue + $adb.SkuName | Should -Be $Sku + $adb.SkuTier | Should -BeNullOrEmpty + #Skip $adb.StorageAccount** + #Skip $adb.SystemData** + $adb.Type | Should -Be 'Microsoft.Databricks/workspaces' + $adb.UiDefinitionUri | Should -BeNullOrEmpty + #Skip $adb.UpdatedBy** + #Skip $adb.Url + $adb.VnetAddressPrefixType | Should -Be 'String' + $adb.VnetAddressPrefixValue | Should -Be '10.139' + #Skip $adb.WorkspaceId + + Test-VerifyTagsForResource -ResourceId $adb.Id -Tags $Tags + + $logs = @( + 'dbfs', 'clusters', 'accounts', 'jobs', 'notebook', + 'ssh', 'workspace', 'secrets', 'sqlPermissions', 'instancePools', + 'sqlanalytics', 'genie', 'globalInitScripts', 'iamRole', 'mlflowExperiment', + 'featureStore', 'RemoteHistoryService', 'mlflowAcledArtifact', 'databrickssql', 'deltaPipelines', + 'modelRegistry', 'repos', 'unityCatalog', 'gitCredentials', 'webTerminal', + 'serverlessRealTimeInference', 'clusterLibraries', 'partnerHub', 'clamAVScan', 'capsule8Dataplane', + 'BrickStoreHttpGateway', 'Dashboards', 'CloudStorageMetadata', 'PredictiveOptimization', 'DataMonitoring', + 'Ingestion', 'MarketplaceConsumer', 'LineageTracking' + ) + Test-VerifyDiagSettings -ResourceId $adb.Id -LogAnalyticsWorkspaceResourceId $LogAnalyticsWorkspaceResourceId -Logs $logs + + $acc = Test-VerifyDatabricksAccessConnector -DatabricksAcCResourceGroupName $DatabricksResourceGroupName -DatabricksAcCName "$($DatabricksName)-acc" -Tags $Tags -DatabricksResourceId $adb.Id + $acc.Id | Should -Be $adb.AccessConnectorId + + # Workaround + $baseName = $DatabricksName -replace '-dbw' -replace '' + + Test-VerifyPrivateEndpoint -Name "$($baseName)$($PEPName0)" -ResourceGroupName $DatabricksResourceGroupName -Tags $Tags -SubnetName $PLSubnetName -ServiceId $null -GroupId 'blob' + Test-VerifyPrivateEndpoint -Name "$($baseName)$($PEPName1)" -ResourceGroupName $DatabricksResourceGroupName -Tags $Tags -SubnetName $PLSubnetName -ServiceId $adb.Id -GroupId 'browser_authentication' + Test-VerifyPrivateEndpoint -Name "$($baseName)$($PEPName2)" -ResourceGroupName $DatabricksResourceGroupName -Tags $Tags -SubnetName $PLSubnetName -ServiceId $adb.Id -GroupId 'databricks_ui_api' + + if ( $BlobNumberOfRecordSets -ne 0 ) { + Test-VerifyDnsZone -Name 'privatelink.blob.core.windows.net' -ResourceGroupName $DatabricksResourceGroupName -Tags $Tags -NumberOfRecordSets $BlobNumberOfRecordSets + } + + if ( $DatabricksNumberOfRecordSets -ne 0 ) { + Test-VerifyDnsZone -Name 'privatelink.azuredatabricks.net' -ResourceGroupName $DatabricksResourceGroupName -Tags $Tags -NumberOfRecordSets $DatabricksNumberOfRecordSets + } + + Test-VerifyLock -ResourceId $adb.Id + Test-VerifyRoleAssignment -ResourceId $adb.Id + + return $adb +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/defaults/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/defaults/custom.tests.ps1 new file mode 100644 index 0000000000..2993ceaa7c --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/defaults/custom.tests.ps1 @@ -0,0 +1,123 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{} # Default has no tags + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $true -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + $vnet = Test-VerifyVirtualNetwork -VirtualNetworkResourceGroupName $virtualNetworkResourceGroupName -VirtualNetworkName $virtualNetworkName ` + -Tags $expectedTags -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -AddressPrefix '192.168.224.0/19' -NumberOfSubnets 1 + + Test-VerifySubnet -Subnet $vnet.Subnets[0] -SubnetName 'private-link-subnet' -SubnetAddressPrefix '192.168.224.0/24' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints 1 -NumberOfIpConfigurations 1 -DelegationServiceName $null + + # Test-VerifySubnet -Subnet $vnet.Subnets[1] -SubnetName 'dbw-frontend-subnet' -SubnetAddressPrefix '192.168.228.0/23' ` + # -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + # Test-VerifySubnet -Subnet $vnet.Subnets[2] -SubnetName 'dbw-backend-subnet' -SubnetAddressPrefix '192.168.230.0/23' ` + # -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + $nsgLogs = @('NetworkSecurityGroupEvent', 'NetworkSecurityGroupRuleCounter') + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[0].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'private-link-subnet' ` + -NumberOfSecurityRules 1 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + # Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[1].NetworkSecurityGroup[0].Id ` + # -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-frontend-subnet' ` + # -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + # Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[2].NetworkSecurityGroup[0].Id ` + # -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-backend-subnet' ` + # -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + Test-VerifyLogAnalyticsWorkspace -LogAnalyticsWorkspaceResourceGroupName $logAnalyticsWorkspaceResourceGroupName ` + -LogAnalyticsWorkspaceName $logAnalyticsWorkspaceName -Tags $expectedTags -Sku 'PerGB2018' -RetentionInDays 365 -DailyQuotaGb -1 + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + Test-VerifyKeyVault -KeyVaultResourceGroupName $keyVaultResourceGroupName -KeyVaultName $keyVaultName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'Premium' -EnableSoftDelete $true -RetentionInDays 90 -PEPName '-PEP' ` + -NumberOfRecordSets 2 -SubnetName 'private-link-subnet' -PublicNetworkAccess 'Disabled' -IpAddressRanges $null + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + # Not relevant for this deployment + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/defaults/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..c44e8f45f2 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,74 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawmin' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + advancedOptions: { + keyVault: { + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/max/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/max/custom.tests.ps1 new file mode 100644 index 0000000000..79d304745d --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/max/custom.tests.ps1 @@ -0,0 +1,126 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso MAX Team'; CostCenter = '123459876' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + $vnet = Test-VerifyVirtualNetwork -VirtualNetworkResourceGroupName $virtualNetworkResourceGroupName -VirtualNetworkName $virtualNetworkName ` + -Tags $expectedTags -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -AddressPrefix '192.168.224.0/19' -NumberOfSubnets 3 + + Test-VerifySubnet -Subnet $vnet.Subnets[0] -SubnetName 'private-link-subnet' -SubnetAddressPrefix '192.168.224.0/24' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints 4 -NumberOfIpConfigurations 5 -DelegationServiceName $null + + Test-VerifySubnet -Subnet $vnet.Subnets[1] -SubnetName 'dbw-frontend-subnet' -SubnetAddressPrefix '192.168.228.0/23' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + Test-VerifySubnet -Subnet $vnet.Subnets[2] -SubnetName 'dbw-backend-subnet' -SubnetAddressPrefix '192.168.230.0/23' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + $nsgLogs = @('NetworkSecurityGroupEvent', 'NetworkSecurityGroupRuleCounter') + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[0].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'private-link-subnet' ` + -NumberOfSecurityRules 1 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[1].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-frontend-subnet' ` + -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[2].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-backend-subnet' ` + -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + Test-VerifyLogAnalyticsWorkspace -LogAnalyticsWorkspaceResourceGroupName $logAnalyticsWorkspaceResourceGroupName ` + -LogAnalyticsWorkspaceName $logAnalyticsWorkspaceName -Tags $expectedTags -Sku 'PerGB2018' -RetentionInDays 35 -DailyQuotaGb 1 + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + Test-VerifyKeyVault -KeyVaultResourceGroupName $keyVaultResourceGroupName -KeyVaultName $keyVaultName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'Standard' -EnableSoftDelete $false -RetentionInDays 7 -PEPName '-PEP' ` + -NumberOfRecordSets 2 -SubnetName 'private-link-subnet' -PublicNetworkAccess 'Enabled' -IpAddressRanges @('104.43.16.94/32') + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + Test-VerifyDatabricks -DatabricksResourceGroupName $databricksResourceGroupName -DatabricksName $databricksName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'premium' -VirtualNetworkResourceId $virtualNetworkResourceId ` + -PrivateSubnetName 'dbw-backend-subnet' -PublicSubnetName 'dbw-frontend-subnet' -PEPName0 '-sa-blob-PEP' -PEPName1 '-dbw-auth-PEP' -PEPName2 '-dbw-ui-PEP' ` + -BlobNumberOfRecordSets 2 -DatabricksNumberOfRecordSets 4 -PLSubnetName 'private-link-subnet' -PublicNetworkAccess 'Enabled' -RequiredNsgRule 'AllRules' + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/max/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..399caddfc5 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/max/main.test.bicep @@ -0,0 +1,86 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawmax' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: enforcedLocation + tags: { + Owner: 'Contoso MAX Team' + CostCenter: '123459876' + } + enableDatabricks: true + advancedOptions: { + networkAcls: { ipRules: ['104.43.16.94'] } + logAnalyticsWorkspace: { dataRetention: 35, dailyQuotaGb: 1 } + keyVault: { + createMode: 'default' + sku: 'standard' + enableSoftDelete: false + softDeleteRetentionInDays: 7 + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/min-priv/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/min-priv/custom.tests.ps1 new file mode 100644 index 0000000000..97fb841fb2 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/min-priv/custom.tests.ps1 @@ -0,0 +1,123 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso'; CostCenter = '123-456-789' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $true -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + $vnet = Test-VerifyVirtualNetwork -VirtualNetworkResourceGroupName $virtualNetworkResourceGroupName -VirtualNetworkName $virtualNetworkName ` + -Tags $expectedTags -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -AddressPrefix '192.168.224.0/19' -NumberOfSubnets 1 + + Test-VerifySubnet -Subnet $vnet.Subnets[0] -SubnetName 'private-link-subnet' -SubnetAddressPrefix '192.168.224.0/24' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints 1 -NumberOfIpConfigurations 1 -DelegationServiceName $null + + # Test-VerifySubnet -Subnet $vnet.Subnets[1] -SubnetName 'dbw-frontend-subnet' -SubnetAddressPrefix '192.168.228.0/23' ` + # -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + # Test-VerifySubnet -Subnet $vnet.Subnets[2] -SubnetName 'dbw-backend-subnet' -SubnetAddressPrefix '192.168.230.0/23' ` + # -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + $nsgLogs = @('NetworkSecurityGroupEvent', 'NetworkSecurityGroupRuleCounter') + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[0].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'private-link-subnet' ` + -NumberOfSecurityRules 1 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + # Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[1].NetworkSecurityGroup[0].Id ` + # -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-frontend-subnet' ` + # -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + # Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[2].NetworkSecurityGroup[0].Id ` + # -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-backend-subnet' ` + # -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + Test-VerifyLogAnalyticsWorkspace -LogAnalyticsWorkspaceResourceGroupName $logAnalyticsWorkspaceResourceGroupName ` + -LogAnalyticsWorkspaceName $logAnalyticsWorkspaceName -Tags $expectedTags -Sku 'PerGB2018' -RetentionInDays 365 -DailyQuotaGb -1 + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + Test-VerifyKeyVault -KeyVaultResourceGroupName $keyVaultResourceGroupName -KeyVaultName $keyVaultName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'Premium' -EnableSoftDelete $true -RetentionInDays 90 -PEPName '-PEP' ` + -NumberOfRecordSets 2 -SubnetName 'private-link-subnet' -PublicNetworkAccess 'Disabled' -IpAddressRanges $null + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + # Not relevant for this deployment + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/min-priv/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/min-priv/main.test.bicep new file mode 100644 index 0000000000..0a2f6c69ed --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/min-priv/main.test.bicep @@ -0,0 +1,79 @@ +targetScope = 'subscription' + +metadata name = 'Minimal Deployment - fully private' +metadata description = 'Isolated network deployment (Minimalistic) - fully private.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawminpriv' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + tags: { + Owner: 'Contoso' + CostCenter: '123-456-789' + } + enableDatabricks: false + advancedOptions: { + keyVault: { + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/min-pub/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/min-pub/custom.tests.ps1 new file mode 100644 index 0000000000..9374f497b3 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/min-pub/custom.tests.ps1 @@ -0,0 +1,123 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso'; CostCenter = '123-456-789' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $true -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + $vnet = Test-VerifyVirtualNetwork -VirtualNetworkResourceGroupName $virtualNetworkResourceGroupName -VirtualNetworkName $virtualNetworkName ` + -Tags $expectedTags -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -AddressPrefix '192.168.224.0/19' -NumberOfSubnets 1 + + Test-VerifySubnet -Subnet $vnet.Subnets[0] -SubnetName 'private-link-subnet' -SubnetAddressPrefix '192.168.224.0/24' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints 1 -NumberOfIpConfigurations 1 -DelegationServiceName $null + + # Test-VerifySubnet -Subnet $vnet.Subnets[1] -SubnetName 'dbw-frontend-subnet' -SubnetAddressPrefix '192.168.228.0/23' ` + # -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + # Test-VerifySubnet -Subnet $vnet.Subnets[2] -SubnetName 'dbw-backend-subnet' -SubnetAddressPrefix '192.168.230.0/23' ` + # -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + $nsgLogs = @('NetworkSecurityGroupEvent', 'NetworkSecurityGroupRuleCounter') + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[0].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'private-link-subnet' ` + -NumberOfSecurityRules 1 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + # Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[1].NetworkSecurityGroup[0].Id ` + # -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-frontend-subnet' ` + # -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + # Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[2].NetworkSecurityGroup[0].Id ` + # -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-backend-subnet' ` + # -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + Test-VerifyLogAnalyticsWorkspace -LogAnalyticsWorkspaceResourceGroupName $logAnalyticsWorkspaceResourceGroupName ` + -LogAnalyticsWorkspaceName $logAnalyticsWorkspaceName -Tags $expectedTags -Sku 'PerGB2018' -RetentionInDays 365 -DailyQuotaGb -1 + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + Test-VerifyKeyVault -KeyVaultResourceGroupName $keyVaultResourceGroupName -KeyVaultName $keyVaultName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'Premium' -EnableSoftDelete $true -RetentionInDays 90 -PEPName '-PEP' ` + -NumberOfRecordSets 2 -SubnetName 'private-link-subnet' -PublicNetworkAccess 'Enabled' -IpAddressRanges @('104.43.16.94/32') + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + # Not relevant for this deployment + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/min-pub/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/min-pub/main.test.bicep new file mode 100644 index 0000000000..228a47f1ce --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/min-pub/main.test.bicep @@ -0,0 +1,80 @@ +targetScope = 'subscription' + +metadata name = 'Minimal Deployment - allowed IP address' +metadata description = 'Isolated network deployment (Minimalistic) - allowed IP address.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawminpu' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + tags: { + Owner: 'Contoso' + CostCenter: '123-456-789' + } + enableDatabricks: false + advancedOptions: { + networkAcls: { ipRules: ['104.43.16.94'] } + keyVault: { + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-priv/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-priv/custom.tests.ps1 new file mode 100644 index 0000000000..87735bb251 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-priv/custom.tests.ps1 @@ -0,0 +1,126 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso'; CostCenter = '123-456-789' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + $vnet = Test-VerifyVirtualNetwork -VirtualNetworkResourceGroupName $virtualNetworkResourceGroupName -VirtualNetworkName $virtualNetworkName ` + -Tags $expectedTags -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -AddressPrefix '192.168.224.0/19' -NumberOfSubnets 3 + + Test-VerifySubnet -Subnet $vnet.Subnets[0] -SubnetName 'private-link-subnet' -SubnetAddressPrefix '192.168.224.0/24' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints 4 -NumberOfIpConfigurations 5 -DelegationServiceName $null + + Test-VerifySubnet -Subnet $vnet.Subnets[1] -SubnetName 'dbw-frontend-subnet' -SubnetAddressPrefix '192.168.228.0/23' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + Test-VerifySubnet -Subnet $vnet.Subnets[2] -SubnetName 'dbw-backend-subnet' -SubnetAddressPrefix '192.168.230.0/23' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + $nsgLogs = @('NetworkSecurityGroupEvent', 'NetworkSecurityGroupRuleCounter') + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[0].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'private-link-subnet' ` + -NumberOfSecurityRules 1 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[1].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-frontend-subnet' ` + -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[2].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-backend-subnet' ` + -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + Test-VerifyLogAnalyticsWorkspace -LogAnalyticsWorkspaceResourceGroupName $logAnalyticsWorkspaceResourceGroupName ` + -LogAnalyticsWorkspaceName $logAnalyticsWorkspaceName -Tags $expectedTags -Sku 'PerGB2018' -RetentionInDays 365 -DailyQuotaGb -1 + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + Test-VerifyKeyVault -KeyVaultResourceGroupName $keyVaultResourceGroupName -KeyVaultName $keyVaultName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'Premium' -EnableSoftDelete $true -RetentionInDays 90 -PEPName '-PEP' ` + -NumberOfRecordSets 2 -SubnetName 'private-link-subnet' -PublicNetworkAccess 'Disabled' -IpAddressRanges $null + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + Test-VerifyDatabricks -DatabricksResourceGroupName $databricksResourceGroupName -DatabricksName $databricksName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'premium' -VirtualNetworkResourceId $virtualNetworkResourceId ` + -PrivateSubnetName 'dbw-backend-subnet' -PublicSubnetName 'dbw-frontend-subnet' -PEPName0 '-sa-blob-PEP' -PEPName1 '-dbw-auth-PEP' -PEPName2 '-dbw-ui-PEP' ` + -BlobNumberOfRecordSets 2 -DatabricksNumberOfRecordSets 4 -PLSubnetName 'private-link-subnet' -PublicNetworkAccess 'Disabled' -RequiredNsgRule 'NoAzureDatabricksRules' + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-priv/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-priv/main.test.bicep new file mode 100644 index 0000000000..bdb5e3342e --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-priv/main.test.bicep @@ -0,0 +1,79 @@ +targetScope = 'subscription' + +metadata name = 'Use Case 1 - fully private' +metadata description = 'Isolated network deployment - fully private.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawu1pr' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + tags: { + Owner: 'Contoso' + CostCenter: '123-456-789' + } + advancedOptions: { + keyVault: { + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + enableDatabricks: true + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-pub/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-pub/custom.tests.ps1 new file mode 100644 index 0000000000..3f81afeb31 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-pub/custom.tests.ps1 @@ -0,0 +1,126 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso'; CostCenter = '123-456-789' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + $vnet = Test-VerifyVirtualNetwork -VirtualNetworkResourceGroupName $virtualNetworkResourceGroupName -VirtualNetworkName $virtualNetworkName ` + -Tags $expectedTags -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -AddressPrefix '192.168.224.0/19' -NumberOfSubnets 3 + + Test-VerifySubnet -Subnet $vnet.Subnets[0] -SubnetName 'private-link-subnet' -SubnetAddressPrefix '192.168.224.0/24' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints 4 -NumberOfIpConfigurations 5 -DelegationServiceName $null + + Test-VerifySubnet -Subnet $vnet.Subnets[1] -SubnetName 'dbw-frontend-subnet' -SubnetAddressPrefix '192.168.228.0/23' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + Test-VerifySubnet -Subnet $vnet.Subnets[2] -SubnetName 'dbw-backend-subnet' -SubnetAddressPrefix '192.168.230.0/23' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + $nsgLogs = @('NetworkSecurityGroupEvent', 'NetworkSecurityGroupRuleCounter') + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[0].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'private-link-subnet' ` + -NumberOfSecurityRules 1 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[1].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-frontend-subnet' ` + -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[2].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-backend-subnet' ` + -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + Test-VerifyLogAnalyticsWorkspace -LogAnalyticsWorkspaceResourceGroupName $logAnalyticsWorkspaceResourceGroupName ` + -LogAnalyticsWorkspaceName $logAnalyticsWorkspaceName -Tags $expectedTags -Sku 'PerGB2018' -RetentionInDays 365 -DailyQuotaGb -1 + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + Test-VerifyKeyVault -KeyVaultResourceGroupName $keyVaultResourceGroupName -KeyVaultName $keyVaultName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'Premium' -EnableSoftDelete $true -RetentionInDays 90 -PEPName '-PEP' ` + -NumberOfRecordSets 2 -SubnetName 'private-link-subnet' -PublicNetworkAccess 'Enabled' -IpAddressRanges @('104.43.16.94/32') + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + Test-VerifyDatabricks -DatabricksResourceGroupName $databricksResourceGroupName -DatabricksName $databricksName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'premium' -VirtualNetworkResourceId $virtualNetworkResourceId ` + -PrivateSubnetName 'dbw-backend-subnet' -PublicSubnetName 'dbw-frontend-subnet' -PEPName0 '-sa-blob-PEP' -PEPName1 '-dbw-auth-PEP' -PEPName2 '-dbw-ui-PEP' ` + -BlobNumberOfRecordSets 2 -DatabricksNumberOfRecordSets 4 -PLSubnetName 'private-link-subnet' -PublicNetworkAccess 'Enabled' -RequiredNsgRule 'AllRules' + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-pub/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-pub/main.test.bicep new file mode 100644 index 0000000000..2e1618b23c --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc01-pub/main.test.bicep @@ -0,0 +1,80 @@ +targetScope = 'subscription' + +metadata name = 'Use Case 1 - allowed IP address' +metadata description = 'Isolated network deployment - allowed IP address.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawu1pu' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + tags: { + Owner: 'Contoso' + CostCenter: '123-456-789' + } + enableDatabricks: true + advancedOptions: { + networkAcls: { ipRules: ['104.43.16.94'] } + keyVault: { + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-priv/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-priv/custom.tests.ps1 new file mode 100644 index 0000000000..cfd035d7af --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-priv/custom.tests.ps1 @@ -0,0 +1,103 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso'; CostCenter = '123-456-789' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + # Not relevant for the custom VNET deployment + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + Test-VerifyLogAnalyticsWorkspace -LogAnalyticsWorkspaceResourceGroupName $logAnalyticsWorkspaceResourceGroupName ` + -LogAnalyticsWorkspaceName $logAnalyticsWorkspaceName -Tags $expectedTags -Sku 'PerGB2018' -RetentionInDays 365 -DailyQuotaGb -1 + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + Test-VerifyKeyVault -KeyVaultResourceGroupName $keyVaultResourceGroupName -KeyVaultName $keyVaultName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'Premium' -EnableSoftDelete $true -RetentionInDays 90 -PEPName '-PEP' ` + -NumberOfRecordSets 0 -SubnetName 'private-link-subnet' -PublicNetworkAccess 'Disabled' -IpAddressRanges $null + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + Test-VerifyDatabricks -DatabricksResourceGroupName $databricksResourceGroupName -DatabricksName $databricksName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'premium' -VirtualNetworkResourceId $virtualNetworkResourceId ` + -PrivateSubnetName 'dbw-backend-subnet' -PublicSubnetName 'dbw-frontend-subnet' -PEPName0 '-sa-blob-PEP' -PEPName1 '-dbw-auth-PEP' -PEPName2 '-dbw-ui-PEP' ` + -BlobNumberOfRecordSets 0 -DatabricksNumberOfRecordSets 0 -PLSubnetName 'private-link-subnet' -PublicNetworkAccess 'Disabled' -RequiredNsgRule 'NoAzureDatabricksRules' + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-priv/dependencies.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-priv/dependencies.bicep new file mode 100644 index 0000000000..e739ce91fb --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-priv/dependencies.bicep @@ -0,0 +1,223 @@ +@description('Optional. The location to deploy to.') +param location string + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +var subnetName01 = 'private-link-subnet' +var subnetName02 = 'dbw-frontend-subnet' +var subnetName03 = 'dbw-backend-subnet' + +var vnetAddressPrefix = '10.0.0.0/20' + +var nsgNamePrivateLink = 'nsg-private-link' +var nsgNameDbwFrontend = 'nsg-dbw-frontend' +var nsgNameDbwBackend = 'nsg-dbw-backend' +var nsgRulesPrivateLink = [ + { + name: 'PrivateLinkDenyAllOutbound' + properties: { + description: 'Private Link subnet should not initiate any Outbound Connections' + access: 'Deny' + direction: 'Outbound' + priority: 100 + protocol: '*' + sourceAddressPrefix: '*' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRange: '*' + } + } +] +var nsgRulesDbw = [ + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-inbound' + properties: { + description: 'Required for worker nodes communication within a cluster' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-webapp' + properties: { + description: 'Required for workers communication with Databricks Webapp' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'AzureDatabricks' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-sql' + properties: { + description: 'Required for workers communication with Azure SQL services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '3306' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Sql' + access: 'Allow' + priority: 101 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-storage' + properties: { + description: 'Required for workers communication with Azure Storage services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Storage' + access: 'Allow' + priority: 102 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-outbound' + properties: { + description: 'Required for worker nodes communication within a cluster.' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 103 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-eventhub' + properties: { + description: 'Required for worker communication with Azure Eventhub services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '9093' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'EventHub' + access: 'Allow' + priority: 104 + direction: 'Outbound' + } + } + { + name: 'deny-hop-outbound' + properties: { + description: 'Subnet should not initiate any management Outbound Connections' + priority: 200 + access: 'Deny' + protocol: 'Tcp' + direction: 'Outbound' + sourceAddressPrefix: 'VirtualNetwork' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRanges: [ + '3389' + '22' + ] + } + } +] + +var subnets = [ + { + name: subnetName01 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 0) + networkSecurityGroupResourceId: nsgPrivateLink.outputs.resourceId + } + { + name: subnetName02 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 1) + networkSecurityGroupResourceId: nsgDbwFrontend.outputs.resourceId + delegations: [ + { + name: 'Microsoft.Databricks/workspaces' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } + { + name: subnetName03 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 2) + networkSecurityGroupResourceId: nsgDbwBackend.outputs.resourceId + delegations: [ + { + name: 'Microsoft.Databricks/workspaces' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } +] + +module vnet 'br/public:avm/res/network/virtual-network:0.2.0' = { + name: virtualNetworkName + params: { + // Required parameters + addressPrefixes: [ + vnetAddressPrefix + ] + name: virtualNetworkName + // Non-required parameters + diagnosticSettings: [] + dnsServers: [] + location: location + subnets: subnets + } +} + +module nsgPrivateLink 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNamePrivateLink + params: { + // Required parameters + name: nsgNamePrivateLink + // Non-required parameters + location: location + securityRules: nsgRulesPrivateLink + } +} + +module nsgDbwFrontend 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNameDbwFrontend + params: { + // Required parameters + name: nsgNameDbwFrontend + // Non-required parameters + location: location + securityRules: nsgRulesDbw + } +} + +module nsgDbwBackend 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNameDbwBackend + params: { + // Required parameters + name: nsgNameDbwBackend + // Non-required parameters + location: location + securityRules: nsgRulesDbw + } +} + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = vnet.outputs.resourceId + +@description('The resource IDs of the deployed subnets.') +output subnetResourceIds array = vnet.outputs.subnetResourceIds diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-priv/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-priv/main.test.bicep new file mode 100644 index 0000000000..b86e618ce3 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-priv/main.test.bicep @@ -0,0 +1,96 @@ +targetScope = 'subscription' + +metadata name = 'Use Case 2 - fully private' +metadata description = 'Deployment in an Existing, Enterprise-Specific Virtual Network - fully private.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawu2pr' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + location: enforcedLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + tags: { + Owner: 'Contoso' + CostCenter: '123-456-789' + } + enableDatabricks: true + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + advancedOptions: { + virtualNetwork: { + subnetNamePrivateLink: last(split(nestedDependencies.outputs.subnetResourceIds[0], '/')) + } + databricks: { + subnetNameFrontend: last(split(nestedDependencies.outputs.subnetResourceIds[1], '/')) + subnetNameBackend: last(split(nestedDependencies.outputs.subnetResourceIds[2], '/')) + } + keyVault: { + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-pub/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-pub/custom.tests.ps1 new file mode 100644 index 0000000000..d05cb703d8 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-pub/custom.tests.ps1 @@ -0,0 +1,103 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso'; CostCenter = '123-456-789' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + # Not relevant for the custom VNET deployment + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + Test-VerifyLogAnalyticsWorkspace -LogAnalyticsWorkspaceResourceGroupName $logAnalyticsWorkspaceResourceGroupName ` + -LogAnalyticsWorkspaceName $logAnalyticsWorkspaceName -Tags $expectedTags -Sku 'PerGB2018' -RetentionInDays 365 -DailyQuotaGb -1 + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + Test-VerifyKeyVault -KeyVaultResourceGroupName $keyVaultResourceGroupName -KeyVaultName $keyVaultName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'Premium' -EnableSoftDelete $true -RetentionInDays 90 -PEPName '-PEP' ` + -NumberOfRecordSets 0 -SubnetName 'private-link-subnet' -PublicNetworkAccess 'Enabled' -IpAddressRanges @('104.43.16.94/32') + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + Test-VerifyDatabricks -DatabricksResourceGroupName $databricksResourceGroupName -DatabricksName $databricksName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'premium' -VirtualNetworkResourceId $virtualNetworkResourceId ` + -PrivateSubnetName 'dbw-backend-subnet' -PublicSubnetName 'dbw-frontend-subnet' -PEPName0 '-sa-blob-PEP' -PEPName1 '-dbw-auth-PEP' -PEPName2 '-dbw-ui-PEP' ` + -BlobNumberOfRecordSets 0 -DatabricksNumberOfRecordSets 0 -PLSubnetName 'private-link-subnet' -PublicNetworkAccess 'Enabled' -RequiredNsgRule 'AllRules' + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-pub/dependencies.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-pub/dependencies.bicep new file mode 100644 index 0000000000..e739ce91fb --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-pub/dependencies.bicep @@ -0,0 +1,223 @@ +@description('Optional. The location to deploy to.') +param location string + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +var subnetName01 = 'private-link-subnet' +var subnetName02 = 'dbw-frontend-subnet' +var subnetName03 = 'dbw-backend-subnet' + +var vnetAddressPrefix = '10.0.0.0/20' + +var nsgNamePrivateLink = 'nsg-private-link' +var nsgNameDbwFrontend = 'nsg-dbw-frontend' +var nsgNameDbwBackend = 'nsg-dbw-backend' +var nsgRulesPrivateLink = [ + { + name: 'PrivateLinkDenyAllOutbound' + properties: { + description: 'Private Link subnet should not initiate any Outbound Connections' + access: 'Deny' + direction: 'Outbound' + priority: 100 + protocol: '*' + sourceAddressPrefix: '*' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRange: '*' + } + } +] +var nsgRulesDbw = [ + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-inbound' + properties: { + description: 'Required for worker nodes communication within a cluster' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-webapp' + properties: { + description: 'Required for workers communication with Databricks Webapp' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'AzureDatabricks' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-sql' + properties: { + description: 'Required for workers communication with Azure SQL services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '3306' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Sql' + access: 'Allow' + priority: 101 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-storage' + properties: { + description: 'Required for workers communication with Azure Storage services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Storage' + access: 'Allow' + priority: 102 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-outbound' + properties: { + description: 'Required for worker nodes communication within a cluster.' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 103 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-eventhub' + properties: { + description: 'Required for worker communication with Azure Eventhub services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '9093' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'EventHub' + access: 'Allow' + priority: 104 + direction: 'Outbound' + } + } + { + name: 'deny-hop-outbound' + properties: { + description: 'Subnet should not initiate any management Outbound Connections' + priority: 200 + access: 'Deny' + protocol: 'Tcp' + direction: 'Outbound' + sourceAddressPrefix: 'VirtualNetwork' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRanges: [ + '3389' + '22' + ] + } + } +] + +var subnets = [ + { + name: subnetName01 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 0) + networkSecurityGroupResourceId: nsgPrivateLink.outputs.resourceId + } + { + name: subnetName02 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 1) + networkSecurityGroupResourceId: nsgDbwFrontend.outputs.resourceId + delegations: [ + { + name: 'Microsoft.Databricks/workspaces' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } + { + name: subnetName03 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 2) + networkSecurityGroupResourceId: nsgDbwBackend.outputs.resourceId + delegations: [ + { + name: 'Microsoft.Databricks/workspaces' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } +] + +module vnet 'br/public:avm/res/network/virtual-network:0.2.0' = { + name: virtualNetworkName + params: { + // Required parameters + addressPrefixes: [ + vnetAddressPrefix + ] + name: virtualNetworkName + // Non-required parameters + diagnosticSettings: [] + dnsServers: [] + location: location + subnets: subnets + } +} + +module nsgPrivateLink 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNamePrivateLink + params: { + // Required parameters + name: nsgNamePrivateLink + // Non-required parameters + location: location + securityRules: nsgRulesPrivateLink + } +} + +module nsgDbwFrontend 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNameDbwFrontend + params: { + // Required parameters + name: nsgNameDbwFrontend + // Non-required parameters + location: location + securityRules: nsgRulesDbw + } +} + +module nsgDbwBackend 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNameDbwBackend + params: { + // Required parameters + name: nsgNameDbwBackend + // Non-required parameters + location: location + securityRules: nsgRulesDbw + } +} + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = vnet.outputs.resourceId + +@description('The resource IDs of the deployed subnets.') +output subnetResourceIds array = vnet.outputs.subnetResourceIds diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-pub/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-pub/main.test.bicep new file mode 100644 index 0000000000..0de5fdd4b8 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc02-pub/main.test.bicep @@ -0,0 +1,97 @@ +targetScope = 'subscription' + +metadata name = 'Use Case 2 - allowed IP address' +metadata description = 'Deployment in an Existing, Enterprise-Specific Virtual Network - allowed IP address.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawu2pu' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' + params: { + location: enforcedLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + tags: { + Owner: 'Contoso' + CostCenter: '123-456-789' + } + enableDatabricks: true + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + advancedOptions: { + networkAcls: { ipRules: ['104.43.16.94'] } + virtualNetwork: { + subnetNamePrivateLink: last(split(nestedDependencies.outputs.subnetResourceIds[0], '/')) + } + databricks: { + subnetNameFrontend: last(split(nestedDependencies.outputs.subnetResourceIds[1], '/')) + subnetNameBackend: last(split(nestedDependencies.outputs.subnetResourceIds[2], '/')) + } + keyVault: { + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-priv/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-priv/custom.tests.ps1 new file mode 100644 index 0000000000..516ed994ba --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-priv/custom.tests.ps1 @@ -0,0 +1,100 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso'; CostCenter = '123-456-789' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + # Not relevant for the custom VNET deployment + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + # Not relevant for this use case + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + # Not relevant for this use case + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + Test-VerifyDatabricks -DatabricksResourceGroupName $databricksResourceGroupName -DatabricksName $databricksName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'premium' -VirtualNetworkResourceId $virtualNetworkResourceId ` + -PrivateSubnetName 'dbw-backend-subnet' -PublicSubnetName 'dbw-frontend-subnet' -PEPName0 '-sa-blob-PEP' -PEPName1 '-dbw-auth-PEP' -PEPName2 '-dbw-ui-PEP' ` + -BlobNumberOfRecordSets 0 -DatabricksNumberOfRecordSets 0 -PLSubnetName 'private-link-subnet' -PublicNetworkAccess 'Disabled' -RequiredNsgRule 'NoAzureDatabricksRules' + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-priv/dependencies.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-priv/dependencies.bicep new file mode 100644 index 0000000000..b6b77e32b1 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-priv/dependencies.bicep @@ -0,0 +1,253 @@ +@description('Optional. The location to deploy to.') +param location string + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Log Analytics Workspace to create.') +param logAnalyticsWorkspaceName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +var subnetName01 = 'private-link-subnet' +var subnetName02 = 'dbw-frontend-subnet' +var subnetName03 = 'dbw-backend-subnet' + +var vnetAddressPrefix = '10.0.0.0/20' + +var nsgNamePrivateLink = 'nsg-private-link' +var nsgNameDbwFrontend = 'nsg-dbw-frontend' +var nsgNameDbwBackend = 'nsg-dbw-backend' +var nsgRulesPrivateLink = [ + { + name: 'PrivateLinkDenyAllOutbound' + properties: { + description: 'Private Link subnet should not initiate any Outbound Connections' + access: 'Deny' + direction: 'Outbound' + priority: 100 + protocol: '*' + sourceAddressPrefix: '*' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRange: '*' + } + } +] +var nsgRulesDbw = [ + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-inbound' + properties: { + description: 'Required for worker nodes communication within a cluster' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-webapp' + properties: { + description: 'Required for workers communication with Databricks Webapp' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'AzureDatabricks' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-sql' + properties: { + description: 'Required for workers communication with Azure SQL services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '3306' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Sql' + access: 'Allow' + priority: 101 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-storage' + properties: { + description: 'Required for workers communication with Azure Storage services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Storage' + access: 'Allow' + priority: 102 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-outbound' + properties: { + description: 'Required for worker nodes communication within a cluster.' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 103 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-eventhub' + properties: { + description: 'Required for worker communication with Azure Eventhub services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '9093' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'EventHub' + access: 'Allow' + priority: 104 + direction: 'Outbound' + } + } + { + name: 'deny-hop-outbound' + properties: { + description: 'Subnet should not initiate any management Outbound Connections' + priority: 200 + access: 'Deny' + protocol: 'Tcp' + direction: 'Outbound' + sourceAddressPrefix: 'VirtualNetwork' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRanges: [ + '3389' + '22' + ] + } + } +] +var subnets = [ + { + name: subnetName01 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 0) + networkSecurityGroupResourceId: nsgPrivateLink.outputs.resourceId + } + { + name: subnetName02 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 1) + networkSecurityGroupResourceId: nsgDbwFrontend.outputs.resourceId + delegations: [ + { + name: 'Microsoft.Databricks/workspaces' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } + { + name: subnetName03 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 2) + networkSecurityGroupResourceId: nsgDbwBackend.outputs.resourceId + delegations: [ + { + name: 'Microsoft.Databricks/workspaces' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } +] + +module vnet 'br/public:avm/res/network/virtual-network:0.2.0' = { + name: virtualNetworkName + params: { + // Required parameters + addressPrefixes: [ + vnetAddressPrefix + ] + name: virtualNetworkName + // Non-required parameters + dnsServers: [] + location: location + subnets: subnets + } +} + +module nsgPrivateLink 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNamePrivateLink + params: { + // Required parameters + name: nsgNamePrivateLink + // Non-required parameters + location: location + securityRules: nsgRulesPrivateLink + } +} + +module nsgDbwFrontend 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNameDbwFrontend + params: { + // Required parameters + name: nsgNameDbwFrontend + // Non-required parameters + location: location + securityRules: nsgRulesDbw + } +} + +module nsgDbwBackend 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNameDbwBackend + params: { + // Required parameters + name: nsgNameDbwBackend + // Non-required parameters + location: location + securityRules: nsgRulesDbw + } +} + +module log 'br/public:avm/res/operational-insights/workspace:0.5.0' = { + name: logAnalyticsWorkspaceName + params: { + // Required parameters + name: logAnalyticsWorkspaceName + // Non-required parameters + location: location + } +} + +module kv 'br/public:avm/res/key-vault/vault:0.7.0' = { + name: keyVaultName + params: { + // Required parameters + name: keyVaultName + // Non-required parameters + location: location + } +} + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = vnet.outputs.resourceId + +@description('The resource IDs of the deployed subnets.') +output subnetResourceIds array = vnet.outputs.subnetResourceIds + +@description('The resource ID of the created Log Analytics Workspace.') +output logAnalyticsWorkspaceResourceId string = log.outputs.resourceId + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = kv.outputs.resourceId diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-priv/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-priv/main.test.bicep new file mode 100644 index 0000000000..cd51b030f5 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-priv/main.test.bicep @@ -0,0 +1,100 @@ +targetScope = 'subscription' + +metadata name = 'Use Case 3 - fully private' +metadata description = 'Integration with existing core Infrastructure - fully private.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawu3pr' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' + params: { + location: enforcedLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + tags: { + Owner: 'Contoso' + CostCenter: '123-456-789' + } + enableDatabricks: true + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + logAnalyticsWorkspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + advancedOptions: { + virtualNetwork: { + subnetNamePrivateLink: last(split(nestedDependencies.outputs.subnetResourceIds[0], '/')) + } + databricks: { + subnetNameFrontend: last(split(nestedDependencies.outputs.subnetResourceIds[1], '/')) + subnetNameBackend: last(split(nestedDependencies.outputs.subnetResourceIds[2], '/')) + } + keyVault: { + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-pub/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-pub/custom.tests.ps1 new file mode 100644 index 0000000000..fa7bd26fbb --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-pub/custom.tests.ps1 @@ -0,0 +1,100 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso'; CostCenter = '123-456-789' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + # Not relevant for the custom VNET deployment + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + # Not relevant for this use case + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + # Not relevant for this use case + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + Test-VerifyDatabricks -DatabricksResourceGroupName $databricksResourceGroupName -DatabricksName $databricksName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'premium' -VirtualNetworkResourceId $virtualNetworkResourceId ` + -PrivateSubnetName 'dbw-backend-subnet' -PublicSubnetName 'dbw-frontend-subnet' -PEPName0 '-sa-blob-PEP' -PEPName1 '-dbw-auth-PEP' -PEPName2 '-dbw-ui-PEP' ` + -BlobNumberOfRecordSets 0 -DatabricksNumberOfRecordSets 0 -PLSubnetName 'private-link-subnet' -PublicNetworkAccess 'Enabled' -RequiredNsgRule 'AllRules' + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-pub/dependencies.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-pub/dependencies.bicep new file mode 100644 index 0000000000..05038a4969 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-pub/dependencies.bicep @@ -0,0 +1,254 @@ +@description('Optional. The location to deploy to.') +param location string + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Log Analytics Workspace to create.') +param logAnalyticsWorkspaceName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +var subnetName01 = 'private-link-subnet' +var subnetName02 = 'dbw-frontend-subnet' +var subnetName03 = 'dbw-backend-subnet' + +var vnetAddressPrefix = '10.0.0.0/20' + +var nsgNamePrivateLink = 'nsg-private-link' +var nsgNameDbwFrontend = 'nsg-dbw-frontend' +var nsgNameDbwBackend = 'nsg-dbw-backend' +var nsgRulesPrivateLink = [ + { + name: 'PrivateLinkDenyAllOutbound' + properties: { + description: 'Private Link subnet should not initiate any Outbound Connections' + access: 'Deny' + direction: 'Outbound' + priority: 100 + protocol: '*' + sourceAddressPrefix: '*' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRange: '*' + } + } +] +var nsgRulesDbw = [ + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-inbound' + properties: { + description: 'Required for worker nodes communication within a cluster' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-webapp' + properties: { + description: 'Required for workers communication with Databricks Webapp' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'AzureDatabricks' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-sql' + properties: { + description: 'Required for workers communication with Azure SQL services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '3306' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Sql' + access: 'Allow' + priority: 101 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-storage' + properties: { + description: 'Required for workers communication with Azure Storage services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Storage' + access: 'Allow' + priority: 102 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-outbound' + properties: { + description: 'Required for worker nodes communication within a cluster.' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 103 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-eventhub' + properties: { + description: 'Required for worker communication with Azure Eventhub services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '9093' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'EventHub' + access: 'Allow' + priority: 104 + direction: 'Outbound' + } + } + { + name: 'deny-hop-outbound' + properties: { + description: 'Subnet should not initiate any management Outbound Connections' + priority: 200 + access: 'Deny' + protocol: 'Tcp' + direction: 'Outbound' + sourceAddressPrefix: 'VirtualNetwork' + sourcePortRange: '*' + destinationAddressPrefix: '*' + destinationPortRanges: [ + '3389' + '22' + ] + } + } +] +var subnets = [ + { + name: subnetName01 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 0) + networkSecurityGroupResourceId: nsgPrivateLink.outputs.resourceId + } + { + name: subnetName02 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 1) + networkSecurityGroupResourceId: nsgDbwFrontend.outputs.resourceId + delegations: [ + { + name: 'Microsoft.Databricks/workspaces' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } + { + name: subnetName03 + addressPrefix: cidrSubnet(vnetAddressPrefix, 24, 2) + networkSecurityGroupResourceId: nsgDbwBackend.outputs.resourceId + delegations: [ + { + name: 'Microsoft.Databricks/workspaces' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } +] + +module vnet 'br/public:avm/res/network/virtual-network:0.2.0' = { + name: virtualNetworkName + params: { + // Required parameters + addressPrefixes: [ + vnetAddressPrefix + ] + name: virtualNetworkName + // Non-required parameters + dnsServers: [] + location: location + subnets: subnets + } +} + +module nsgPrivateLink 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNamePrivateLink + params: { + // Required parameters + name: nsgNamePrivateLink + // Non-required parameters + location: location + securityRules: nsgRulesPrivateLink + } +} + +module nsgDbwFrontend 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNameDbwFrontend + params: { + // Required parameters + name: nsgNameDbwFrontend + // Non-required parameters + location: location + securityRules: nsgRulesDbw + } +} + +module nsgDbwBackend 'br/public:avm/res/network/network-security-group:0.4.0' = { + name: nsgNameDbwBackend + params: { + // Required parameters + name: nsgNameDbwBackend + // Non-required parameters + location: location + securityRules: nsgRulesDbw + } +} + +module log 'br/public:avm/res/operational-insights/workspace:0.5.0' = { + name: logAnalyticsWorkspaceName + params: { + // Required parameters + name: logAnalyticsWorkspaceName + // Non-required parameters + location: location + } +} + +module kv 'br/public:avm/res/key-vault/vault:0.7.0' = { + name: keyVaultName + params: { + // Required parameters + name: keyVaultName + // Non-required parameters + location: location + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } +} + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = vnet.outputs.resourceId + +@description('The resource IDs of the deployed subnets.') +output subnetResourceIds array = vnet.outputs.subnetResourceIds + +@description('The resource ID of the created Log Analytics Workspace.') +output logAnalyticsWorkspaceResourceId string = log.outputs.resourceId + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = kv.outputs.resourceId diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-pub/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-pub/main.test.bicep new file mode 100644 index 0000000000..f9f64f7716 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/uc03-pub/main.test.bicep @@ -0,0 +1,98 @@ +targetScope = 'subscription' + +metadata name = 'Use Case 3 - allowed IP address' +metadata description = 'Integration with existing core Infrastructure - allowed IP address.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawu3p' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' + params: { + location: enforcedLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-1' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + tags: { + Owner: 'Contoso' + CostCenter: '123-456-789' + } + enableDatabricks: true + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + logAnalyticsWorkspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + advancedOptions: { + networkAcls: { ipRules: ['104.43.16.94'] } + virtualNetwork: { + subnetNamePrivateLink: last(split(nestedDependencies.outputs.subnetResourceIds[0], '/')) + } + databricks: { + subnetNameFrontend: last(split(nestedDependencies.outputs.subnetResourceIds[1], '/')) + subnetNameBackend: last(split(nestedDependencies.outputs.subnetResourceIds[2], '/')) + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/waf-aligned/custom.tests.ps1 b/avm/ptn/data/private-analytical-workspace/tests/e2e/waf-aligned/custom.tests.ps1 new file mode 100644 index 0000000000..5b595270d7 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/waf-aligned/custom.tests.ps1 @@ -0,0 +1,126 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Validate Pattern deployment' { + + BeforeAll { + + . $PSScriptRoot/../../common.tests.ps1 + $expectedTags = @{Owner = 'Contoso'; CostCenter = '123-456-789' } + + $resourceId = $TestInputData.DeploymentOutputs.resourceId.Value + $name = $TestInputData.DeploymentOutputs.name.Value + $location = $TestInputData.DeploymentOutputs.location.Value + $resourceGroupName = $TestInputData.DeploymentOutputs.resourceGroupName.Value + + $virtualNetworkResourceId = $TestInputData.DeploymentOutputs.virtualNetworkResourceId.Value + $virtualNetworkName = $TestInputData.DeploymentOutputs.virtualNetworkName.Value + $virtualNetworkLocation = $TestInputData.DeploymentOutputs.virtualNetworkLocation.Value + $virtualNetworkResourceGroupName = $TestInputData.DeploymentOutputs.virtualNetworkResourceGroupName.Value + + $logAnalyticsWorkspaceResourceId = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceId.Value + $logAnalyticsWorkspaceName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceName.Value + $logAnalyticsWorkspaceLocation = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceLocation.Value + $logAnalyticsWorkspaceResourceGroupName = $TestInputData.DeploymentOutputs.logAnalyticsWorkspaceResourceGroupName.Value + + $keyVaultResourceId = $TestInputData.DeploymentOutputs.keyVaultResourceId.Value + $keyVaultName = $TestInputData.DeploymentOutputs.keyVaultName.Value + $keyVaultLocation = $TestInputData.DeploymentOutputs.keyVaultLocation.Value + $keyVaultResourceGroupName = $TestInputData.DeploymentOutputs.keyVaultResourceGroupName.Value + + $databricksResourceId = $TestInputData.DeploymentOutputs.databricksResourceId.Value + $databricksName = $TestInputData.DeploymentOutputs.databricksName.Value + $databricksLocation = $TestInputData.DeploymentOutputs.databricksLocation.Value + $databricksResourceGroupName = $TestInputData.DeploymentOutputs.databricksResourceGroupName.Value + } + + Context 'Pattern Tests' { + + BeforeAll { + } + + It 'Check Output Variables' { + + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $resourceId -name $name -Location $location -ResourceGroupName $resourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $virtualNetworkResourceId -name $virtualNetworkName -Location $virtualNetworkLocation -ResourceGroupName $virtualNetworkResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $logAnalyticsWorkspaceResourceId -name $logAnalyticsWorkspaceName -Location $logAnalyticsWorkspaceLocation -ResourceGroupName $logAnalyticsWorkspaceResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $keyVaultResourceId -name $keyVaultName -Location $keyVaultLocation -ResourceGroupName $keyVaultResourceGroupName + Test-VerifyOutputVariables -MustBeNullOrEmpty $false -ResourceId $databricksResourceId -name $databricksName -Location $databricksLocation -ResourceGroupName $databricksResourceGroupName + } + + Context 'Network - Azure Virtual Network Tests' { + + BeforeAll { + } + + It 'Check Azure Virtual Network' { + + $vnet = Test-VerifyVirtualNetwork -VirtualNetworkResourceGroupName $virtualNetworkResourceGroupName -VirtualNetworkName $virtualNetworkName ` + -Tags $expectedTags -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -AddressPrefix '192.168.224.0/19' -NumberOfSubnets 3 + + Test-VerifySubnet -Subnet $vnet.Subnets[0] -SubnetName 'private-link-subnet' -SubnetAddressPrefix '192.168.224.0/24' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints 4 -NumberOfIpConfigurations 5 -DelegationServiceName $null + + Test-VerifySubnet -Subnet $vnet.Subnets[1] -SubnetName 'dbw-frontend-subnet' -SubnetAddressPrefix '192.168.228.0/23' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + Test-VerifySubnet -Subnet $vnet.Subnets[2] -SubnetName 'dbw-backend-subnet' -SubnetAddressPrefix '192.168.230.0/23' ` + -NumberOfSecurityGroups 1 -NumberOfPrivateEndpoints $null -NumberOfIpConfigurations $null -DelegationServiceName 'Microsoft.Databricks/workspaces' + + $nsgLogs = @('NetworkSecurityGroupEvent', 'NetworkSecurityGroupRuleCounter') + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[0].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'private-link-subnet' ` + -NumberOfSecurityRules 1 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[1].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-frontend-subnet' ` + -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + + Test-VerifyNetworkSecurityGroup -NetworkSecurityGroupResourceId $vnet.Subnets[2].NetworkSecurityGroup[0].Id ` + -Tags $expectedTags -VirtualNetworkResourceId $virtualNetworkResourceId -SubnetName 'dbw-backend-subnet' ` + -NumberOfSecurityRules 7 -NumberOfDefaultSecurityRules 6 -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Logs $nsgLogs + } + } + + Context 'Monitoring - Azure Log Analytics Workspace Tests' { + + BeforeAll { + } + + It 'Check Azure Log Analytics Workspace' { + + Test-VerifyLogAnalyticsWorkspace -LogAnalyticsWorkspaceResourceGroupName $logAnalyticsWorkspaceResourceGroupName ` + -LogAnalyticsWorkspaceName $logAnalyticsWorkspaceName -Tags $expectedTags -Sku 'PerGB2018' -RetentionInDays 35 -DailyQuotaGb 1 + } + } + + Context 'Secrets - Azure Key Vault Tests' { + + BeforeAll { + } + + It 'Check Azure Key Vault' { + + Test-VerifyKeyVault -KeyVaultResourceGroupName $keyVaultResourceGroupName -KeyVaultName $keyVaultName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'Standard' -EnableSoftDelete $true -RetentionInDays 90 -PEPName '-PEP' ` + -NumberOfRecordSets 2 -SubnetName 'private-link-subnet' -PublicNetworkAccess 'Disabled' -IpAddressRanges $null + } + } + + Context 'Azure Databricks Tests' { + + BeforeAll { + } + + It 'Check Azure Databricks' { + + Test-VerifyDatabricks -DatabricksResourceGroupName $databricksResourceGroupName -DatabricksName $databricksName -Tags $expectedTags ` + -LogAnalyticsWorkspaceResourceId $logAnalyticsWorkspaceResourceId -Sku 'premium' -VirtualNetworkResourceId $virtualNetworkResourceId ` + -PrivateSubnetName 'dbw-backend-subnet' -PublicSubnetName 'dbw-frontend-subnet' -PEPName0 '-sa-blob-PEP' -PEPName1 '-dbw-auth-PEP' -PEPName2 '-dbw-ui-PEP' ` + -BlobNumberOfRecordSets 2 -DatabricksNumberOfRecordSets 4 -PLSubnetName 'private-link-subnet' -PublicNetworkAccess 'Disabled' -RequiredNsgRule 'NoAzureDatabricksRules' + } + } + } +} diff --git a/avm/ptn/data/private-analytical-workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/ptn/data/private-analytical-workspace/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..358e84c2f8 --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,87 @@ +targetScope = 'subscription' + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-data-privateanalyticalworkspace-${serviceShort}-rg' + +// enforcing location due to ADB private link behavior +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dpawwaf' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: enforcedLocation + tags: { + 'hidden-title': 'This is visible in the resource name' + Owner: 'Contoso' + CostCenter: '123-456-789' + } + enableTelemetry: true + enableDatabricks: true + advancedOptions: { + logAnalyticsWorkspace: { dataRetention: 35, dailyQuotaGb: 1 } + keyVault: { + createMode: 'default' + sku: 'standard' + enableSoftDelete: true + softDeleteRetentionInDays: 90 + enablePurgeProtection: false // For the purposes of the test, we disable purge protection + } + } + } + } +] + +output resourceId string = testDeployment[0].outputs.resourceId +output name string = testDeployment[0].outputs.name +output location string = testDeployment[0].outputs.location +output resourceGroupName string = testDeployment[0].outputs.resourceGroupName +output virtualNetworkResourceId string = testDeployment[0].outputs.virtualNetworkResourceId +output virtualNetworkName string = testDeployment[0].outputs.virtualNetworkName +output virtualNetworkLocation string = testDeployment[0].outputs.virtualNetworkLocation +output virtualNetworkResourceGroupName string = testDeployment[0].outputs.virtualNetworkResourceGroupName +output logAnalyticsWorkspaceResourceId string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceId +output logAnalyticsWorkspaceName string = testDeployment[0].outputs.logAnalyticsWorkspaceName +output logAnalyticsWorkspaceLocation string = testDeployment[0].outputs.logAnalyticsWorkspaceLocation +output logAnalyticsWorkspaceResourceGroupName string = testDeployment[0].outputs.logAnalyticsWorkspaceResourceGroupName +output keyVaultResourceId string = testDeployment[0].outputs.keyVaultResourceId +output keyVaultName string = testDeployment[0].outputs.keyVaultName +output keyVaultLocation string = testDeployment[0].outputs.keyVaultLocation +output keyVaultResourceGroupName string = testDeployment[0].outputs.keyVaultResourceGroupName +output databricksResourceId string = testDeployment[0].outputs.databricksResourceId +output databricksName string = testDeployment[0].outputs.databricksName +output databricksLocation string = testDeployment[0].outputs.databricksLocation +output databricksResourceGroupName string = testDeployment[0].outputs.databricksResourceGroupName diff --git a/avm/ptn/data/private-analytical-workspace/version.json b/avm/ptn/data/private-analytical-workspace/version.json new file mode 100644 index 0000000000..8def869ede --- /dev/null +++ b/avm/ptn/data/private-analytical-workspace/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/ptn/deployment-script/import-image-to-acr/README.md b/avm/ptn/deployment-script/import-image-to-acr/README.md index 0e878635e3..82e34a64bd 100644 --- a/avm/ptn/deployment-script/import-image-to-acr/README.md +++ b/avm/ptn/deployment-script/import-image-to-acr/README.md @@ -393,13 +393,13 @@ The managed identity definition for this resource. Required if `assignRbacRole` | Parameter | Type | Description | | :-- | :-- | :-- | -| [`userAssignedResourcesIds`](#parameter-managedidentitiesuserassignedresourcesids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | -### Parameter: `managedIdentities.userAssignedResourcesIds` +### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. -- Required: Yes +- Required: No - Type: array ### Parameter: `managedIdentityName` @@ -497,6 +497,7 @@ The password for the source registry. Required if the source registry is private - Required: No - Type: securestring - Default: `''` +- Example: `keyVault.getSecret("keyVaultSecretName")` ### Parameter: `sourceRegistryUsername` @@ -549,7 +550,8 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/resources/deployment-script:0.4.0` | Remote reference | +| `br/public:avm/res/resources/deployment-script:0.5.0` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Notes diff --git a/avm/ptn/deployment-script/import-image-to-acr/main.bicep b/avm/ptn/deployment-script/import-image-to-acr/main.bicep index e6c532e567..9ae53ae653 100644 --- a/avm/ptn/deployment-script/import-image-to-acr/main.bicep +++ b/avm/ptn/deployment-script/import-image-to-acr/main.bicep @@ -20,8 +20,9 @@ param runOnce bool = false @description('Optional. If set, the `Contributor` role will be granted to the managed identity (passed by the `managedIdentities` parameter or create with the name specified in parameter `managedIdentityName`), which is needed to import images into the Azure Container Registry. Defaults to `true`.') param assignRbacRole bool = true +import { managedIdentityOnlyUserAssignedType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Conditional. The managed identity definition for this resource. Required if `assignRbacRole` is `true` and `managedIdentityName` is `null`.') -param managedIdentities managedIdentitiesType? +param managedIdentities managedIdentityOnlyUserAssignedType? @description('Conditional. Name of the Managed Identity resource to create. Required if `assignRbacRole` is `true` and `managedIdentities` is `null`. Defaults to `id-ContainerRegistryImport`.') param managedIdentityName string? @@ -41,6 +42,7 @@ param sourceRegistryUsername string = '' @description('Optional. The password for the source registry. Required if the source registry is private, or to logon to the public docker registry.') @secure() +@metadata({ example: 'keyVault.getSecret("keyVaultSecretName")' }) param sourceRegistryPassword string = '' @description('Optional. The new image name in the ACR. You can use this to import a publically available image with a custom name for later updating from e.g., your build pipeline.') @@ -87,7 +89,7 @@ param tags object? // Variables // // ============== // -var useExistingManagedIdentity = length(managedIdentities.?userAssignedResourcesIds ?? []) > 0 +var useExistingManagedIdentity = length(managedIdentities.?userAssignedResourceIds ?? []) > 0 // ============== // // Resources // @@ -118,7 +120,7 @@ resource acr 'Microsoft.ContainerRegistry/registries@2023-07-01' existing = { // needed to "convert" resourceIds to principalId resource existingManagedIdentities 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = [ - for resourceId in (managedIdentities.?userAssignedResourcesIds ?? []): if (assignRbacRole) { + for resourceId in (managedIdentities.?userAssignedResourceIds ?? []): if (assignRbacRole) { name: last(split(resourceId, '/')) scope: resourceGroup(split(resourceId, '/')[2], split(resourceId, '/')[4]) // get the resource group from the managed identity, as it could be in another resource group } @@ -132,7 +134,7 @@ resource newManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@20 // assign the Contributor role to the managed identity (new or existing) to import images into the ACR resource acrRoleAssignmentExistingManagedIdentities 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ - for i in range(0, length(assignRbacRole ? (managedIdentities.?userAssignedResourcesIds ?? []) : [])): if (useExistingManagedIdentity && assignRbacRole) { + for i in range(0, length(assignRbacRole ? (managedIdentities.?userAssignedResourceIds ?? []) : [])): if (useExistingManagedIdentity && assignRbacRole) { name: guid('roleAssignment-acr-${existingManagedIdentities[i].name}') scope: acr properties: { @@ -158,7 +160,7 @@ resource acrRoleAssignmentNewManagedIdentity 'Microsoft.Authorization/roleAssign } } -module imageImport 'br/public:avm/res/resources/deployment-script:0.4.0' = { +module imageImport 'br/public:avm/res/resources/deployment-script:0.5.0' = { name: name ?? 'ACR-Import-${last(split(replace(image,':','-'),'/'))}' scope: resourceGroup() params: { @@ -167,7 +169,7 @@ module imageImport 'br/public:avm/res/resources/deployment-script:0.4.0' = { tags: tags managedIdentities: useExistingManagedIdentity ? managedIdentities - : { userAssignedResourcesIds: [newManagedIdentity.id] } + : { userAssignedResourceIds: [newManagedIdentity.id] } kind: 'AzureCLI' runOnce: runOnce azCliVersion: '2.63.0' // available tags are listed here: https://mcr.microsoft.com/v2/azure-cli/tags/list @@ -248,8 +250,3 @@ type importedImageType = { @description('Required. The image name in the Azure Container Registry.') acrHostedImage: string } - -type managedIdentitiesType = { - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourcesIds: string[] -} diff --git a/avm/ptn/deployment-script/import-image-to-acr/main.json b/avm/ptn/deployment-script/import-image-to-acr/main.json index 6bfe24d5cd..72f37ed58c 100644 --- a/avm/ptn/deployment-script/import-image-to-acr/main.json +++ b/avm/ptn/deployment-script/import-image-to-acr/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "17375159703541878382" + "version": "0.30.23.60470", + "templateHash": "11351051395125066237" }, "name": "import-image-to-acr", "description": "This modules deployes an image to an Azure Container Registry.", @@ -30,18 +30,25 @@ } } }, - "managedIdentitiesType": { + "managedIdentityOnlyUserAssignedType": { "type": "object", "properties": { - "userAssignedResourcesIds": { + "userAssignedResourceIds": { "type": "array", "items": { "type": "string" }, + "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." } } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } } } }, @@ -87,7 +94,7 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityOnlyUserAssignedType", "nullable": true, "metadata": { "description": "Conditional. The managed identity definition for this resource. Required if `assignRbacRole` is `true` and `managedIdentityName` is `null`." @@ -122,6 +129,7 @@ "type": "securestring", "defaultValue": "", "metadata": { + "example": "keyVault.getSecret(\"keyVaultSecretName\")", "description": "Optional. The password for the source registry. Required if the source registry is private, or to logon to the public docker registry." } }, @@ -193,7 +201,7 @@ } }, "variables": { - "useExistingManagedIdentity": "[greater(length(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray())), 0)]" + "useExistingManagedIdentity": "[greater(length(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray())), 0)]" }, "resources": { "avmTelemetry": { @@ -225,15 +233,15 @@ "existingManagedIdentities": { "copy": { "name": "existingManagedIdentities", - "count": "[length(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray()))]" + "count": "[length(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()))]" }, "condition": "[parameters('assignRbacRole')]", "existing": true, "type": "Microsoft.ManagedIdentity/userAssignedIdentities", "apiVersion": "2023-01-31", - "subscriptionId": "[split(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray())[copyIndex()], '/')[2]]", - "resourceGroup": "[split(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray())[copyIndex()], '/')[4]]", - "name": "[last(split(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray())[copyIndex()], '/'))]" + "subscriptionId": "[split(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray())[copyIndex()], '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray())[copyIndex()], '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray())[copyIndex()], '/'))]" }, "newManagedIdentity": { "condition": "[and(not(variables('useExistingManagedIdentity')), parameters('assignRbacRole'))]", @@ -246,22 +254,22 @@ "acrRoleAssignmentExistingManagedIdentities": { "copy": { "name": "acrRoleAssignmentExistingManagedIdentities", - "count": "[length(range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray()), createArray()))))]" + "count": "[length(range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), createArray()))))]" }, "condition": "[and(variables('useExistingManagedIdentity'), parameters('assignRbacRole'))]", "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.ContainerRegistry/registries/{0}', parameters('acrName'))]", - "name": "[guid(format('roleAssignment-acr-{0}', last(split(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray())[range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray()), createArray())))[copyIndex()]], '/'))))]", + "name": "[guid(format('roleAssignment-acr-{0}', last(split(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray())[range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), createArray())))[copyIndex()]], '/'))))]", "properties": { - "principalId": "[reference(format('existingManagedIdentities[{0}]', range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray()), createArray())))[copyIndex()])).principalId]", + "principalId": "[reference(format('existingManagedIdentities[{0}]', range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), createArray())))[copyIndex()])).principalId]", "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "principalType": "ServicePrincipal" }, "dependsOn": [ "acr", - "[format('existingManagedIdentities[{0}]', range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray()), createArray())))[copyIndex()])]", - "[format('existingManagedIdentities[{0}]', range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray()), createArray())))[copyIndex()])]" + "[format('existingManagedIdentities[{0}]', range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), createArray())))[copyIndex()])]", + "[format('existingManagedIdentities[{0}]', range(0, length(if(parameters('assignRbacRole'), coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), createArray())))[copyIndex()])]" ] }, "acrRoleAssignmentNewManagedIdentity": { @@ -299,7 +307,7 @@ "tags": { "value": "[parameters('tags')]" }, - "managedIdentities": "[if(variables('useExistingManagedIdentity'), createObject('value', parameters('managedIdentities')), createObject('value', createObject('userAssignedResourcesIds', createArray(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', coalesce(parameters('managedIdentityName'), 'id-ContainerRegistryImport'))))))]", + "managedIdentities": "[if(variables('useExistingManagedIdentity'), createObject('value', parameters('managedIdentities')), createObject('value', createObject('userAssignedResourceIds', createArray(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', coalesce(parameters('managedIdentityName'), 'id-ContainerRegistryImport'))))))]", "kind": { "value": "AzureCLI" }, @@ -378,14 +386,39 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5978422939896103340" + "version": "0.30.23.60470", + "templateHash": "16722602669876377866" }, "name": "Deployment Scripts", "description": "This module deploys Deployment Scripts.", "owner": "Azure/module-maintainers" }, "definitions": { + "environmentVariableType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the environment variable." + } + }, + "secureValue": { + "type": "securestring", + "nullable": true, + "metadata": { + "description": "Conditional. The value of the secure environment variable. Required if `value` is null." + } + }, + "value": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Conditional. The value of the environment variable. Required if `secureValue` is null." + } + } + } + }, "lockType": { "type": "object", "properties": { @@ -409,119 +442,107 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "managedIdentitiesType": { + "managedIdentityOnlyUserAssignedType": { "type": "object", "properties": { - "userAssignedResourcesIds": { + "userAssignedResourceIds": { "type": "array", "items": { "type": "string" }, + "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." } } }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" } - }, - "nullable": true + } }, - "environmentVariableType": { + "roleAssignmentType": { "type": "object", "properties": { "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The name of the environment variable." + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "secureValue": { - "type": "securestring", + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], "nullable": true, "metadata": { - "description": "Required. The value of the secure environment variable." + "description": "Optional. The principal type of the assigned principal ID." } }, - "value": { + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { "type": "string", "nullable": true, "metadata": { - "description": "Required. The value of the environment variable." + "description": "Optional. The Resource Id of the delegated managed identity resource." } } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } } } }, @@ -551,7 +572,8 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityOnlyUserAssignedType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } @@ -681,12 +703,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -725,15 +752,15 @@ "containerGroupName": "[parameters('containerGroupName')]", "subnetIds": "[if(not(empty(coalesce(variables('subnetIds'), createArray()))), variables('subnetIds'), null())]" }, - "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", - "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createObject()))), 'UserAssigned', null()), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]" + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null()), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]" }, "resources": { "storageAccount": { "condition": "[not(empty(parameters('storageAccountResourceId')))]", "existing": true, "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2021-04-01", + "apiVersion": "2023-05-01", "subscriptionId": "[split(if(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountResourceId'), '//'), '/')[2]]", "resourceGroup": "[split(if(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountResourceId'), '////'), '/')[4]]", "name": "[last(split(if(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountResourceId'), 'dummyAccount'), '/'))]" @@ -742,7 +769,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.resources-deploymentscript.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.resources-deploymentscript.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { diff --git a/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/max/dependencies.bicep b/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/max/dependencies.bicep index f68b4451d5..5b6e20b8c1 100644 --- a/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/max/dependencies.bicep +++ b/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/max/dependencies.bicep @@ -18,7 +18,7 @@ param keyVaultName string var ipRange = '10.0.0.0' -module identity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = { +module identity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.0' = { name: managedIdentityName params: { name: managedIdentityName @@ -63,7 +63,7 @@ resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = { } } -module dnsZoneContainerRegistry 'br/public:avm/res/network/private-dns-zone:0.2.5' = { +module dnsZoneContainerRegistry 'br/public:avm/res/network/private-dns-zone:0.6.0' = { name: '${uniqueString(deployment().name, location)}-dnsZone-ACR' params: { name: 'privatelink.azurecr.io' @@ -77,7 +77,7 @@ module dnsZoneContainerRegistry 'br/public:avm/res/network/private-dns-zone:0.2. } } -module storage 'br/public:avm/res/storage/storage-account:0.9.0' = { +module storage 'br/public:avm/res/storage/storage-account:0.9.1' = { name: '${uniqueString(resourceGroup().name, location)}-storage' params: { name: storageAccountName @@ -155,7 +155,7 @@ resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = { } // the container registry to upload the image into -module acr 'br/public:avm/res/container-registry/registry:0.2.0' = { +module acr 'br/public:avm/res/container-registry/registry:0.6.0' = { name: '${uniqueString(resourceGroup().name, location)}-acr' params: { name: acrName @@ -172,10 +172,12 @@ module acr 'br/public:avm/res/container-registry/registry:0.2.0' = { subnetResourceId: vnet::subnet_privateendpoints.id customNetworkInterfaceName: '${uniqueString(resourceGroup().name, location)}-pe-ContainerRegistry-nic' location: location - privateDnsZoneGroupName: 'default' - privateDnsZoneResourceIds: [ - dnsZoneContainerRegistry.outputs.resourceId - ] + privateDnsZoneGroup: { + name: 'default' + privateDnsZoneGroupConfigs: [ + { privateDnsZoneResourceId: dnsZoneContainerRegistry.outputs.resourceId } + ] + } isManualConnection: false service: 'registry' } diff --git a/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/max/main.test.bicep b/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/max/main.test.bicep index 8cd3fd3db1..5bcd7b3eb4 100644 --- a/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/max/main.test.bicep +++ b/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/max/main.test.bicep @@ -72,7 +72,7 @@ module testDeployment '../../../main.bicep' = [ newImageName: 'application/your-image-name:tag' cleanupPreference: 'OnExpiration' assignRbacRole: true - managedIdentities: { userAssignedResourcesIds: [dependencies.outputs.managedIdentityResourceId] } + managedIdentities: { userAssignedResourceIds: [dependencies.outputs.managedIdentityResourceId] } overwriteExistingImage: true storageAccountResourceId: dependencies.outputs.storageAccountResourceId subnetResourceIds: [dependencies.outputs.deploymentScriptSubnetResourceId] diff --git a/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/waf-aligned/dependencies.bicep b/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/waf-aligned/dependencies.bicep index 545c0c6fcc..1048ff244d 100644 --- a/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/waf-aligned/dependencies.bicep @@ -7,7 +7,7 @@ param managedIdentityName string @description('Required. The name of the Azure Container Registry.') param acrName string -module identity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = { +module identity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.0' = { name: managedIdentityName params: { name: managedIdentityName @@ -16,7 +16,7 @@ module identity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1 } // the container registry to upload the image into -module acr 'br/public:avm/res/container-registry/registry:0.2.0' = { +module acr 'br/public:avm/res/container-registry/registry:0.6.0' = { name: '${uniqueString(resourceGroup().name, location)}-acr' params: { name: acrName diff --git a/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/waf-aligned/main.test.bicep b/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/waf-aligned/main.test.bicep index b9dc712fab..5189921d0c 100644 --- a/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/ptn/deployment-script/import-image-to-acr/tests/e2e/waf-aligned/main.test.bicep @@ -55,7 +55,7 @@ module testDeployment '../../../main.bicep' = [ acrName: dependencies.outputs.acrName image: 'mcr.microsoft.com/k8se/quickstart-jobs:latest' overwriteExistingImage: true - managedIdentities: { userAssignedResourcesIds: [dependencies.outputs.managedIdentityResourceId] } + managedIdentities: { userAssignedResourceIds: [dependencies.outputs.managedIdentityResourceId] } } } ] diff --git a/avm/ptn/deployment-script/import-image-to-acr/version.json b/avm/ptn/deployment-script/import-image-to-acr/version.json index 17dd49a0b9..aa34c4d0f5 100644 --- a/avm/ptn/deployment-script/import-image-to-acr/version.json +++ b/avm/ptn/deployment-script/import-image-to-acr/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.3", + "version": "0.4", "pathFilters": [ "./main.json" ] diff --git a/avm/ptn/lz/sub-vending/README.md b/avm/ptn/lz/sub-vending/README.md index c5abe03e9f..d7a98d231b 100644 --- a/avm/ptn/lz/sub-vending/README.md +++ b/avm/ptn/lz/sub-vending/README.md @@ -25,9 +25,9 @@ This module deploys a subscription to accelerate deployment of landing zones. Fo | `Microsoft.Network/privateEndpoints` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints) | | `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints/privateDnsZoneGroups) | | `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/virtualHubs/hubVirtualNetworkConnections) | -| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks) | -| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/subnets) | -| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/virtualNetworkPeerings) | +| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks) | +| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/subnets) | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/virtualNetworkPeerings) | | `Microsoft.Resources/deploymentScripts` | [2023-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Resources/2023-08-01/deploymentScripts) | | `Microsoft.Resources/resourceGroups` | [2021-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Resources/2021-04-01/resourceGroups) | | `Microsoft.Resources/tags` | [2019-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Resources/tags) | @@ -55,7 +55,8 @@ The following section provides usage examples for the module, which were used to - [Using only defaults.](#example-1-using-only-defaults) - [Hub and spoke topology.](#example-2-hub-and-spoke-topology) -- [Vwan topology.](#example-3-vwan-topology) +- [Using RBAC conditions.](#example-3-using-rbac-conditions) +- [Vwan topology.](#example-4-vwan-topology) ### Example 1: _Using only defaults._ @@ -396,7 +397,173 @@ param virtualNetworkUseRemoteGateways = false

-### Example 3: _Vwan topology._ +### Example 3: _Using RBAC conditions._ + +This instance deploys the module with RBAC conditions for the role assignments. + + +

+ +via Bicep module + +```bicep +module subVending 'br/public:avm/ptn/lz/sub-vending:' = { + name: 'subVendingDeployment' + params: { + resourceProviders: {} + roleAssignmentEnabled: true + roleAssignments: [ + { + definition: '/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168' + principalId: '896b1162-be44-4b28-888a-d01acc1b4271' + relativeScope: '' + roleAssignmentCondition: { + roleConditionType: { + principleTypesToAssign: [ + 'Group' + 'ServicePrincipal' + ] + rolesToAssign: [ + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ] + templateName: 'constrainRolesAndPrincipalTypes' + } + } + } + ] + subscriptionAliasEnabled: true + subscriptionAliasName: '' + subscriptionBillingScope: '' + subscriptionDisplayName: '' + subscriptionManagementGroupAssociationEnabled: true + subscriptionManagementGroupId: 'bicep-lz-vending-automation-child' + subscriptionTags: { + namePrefix: '' + serviceShort: '' + } + subscriptionWorkload: 'Production' + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "resourceProviders": { + "value": {} + }, + "roleAssignmentEnabled": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "definition": "/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168", + "principalId": "896b1162-be44-4b28-888a-d01acc1b4271", + "relativeScope": "", + "roleAssignmentCondition": { + "roleConditionType": { + "principleTypesToAssign": [ + "Group", + "ServicePrincipal" + ], + "rolesToAssign": [ + "b24988ac-6180-42a0-ab88-20f7382dd24c" + ], + "templateName": "constrainRolesAndPrincipalTypes" + } + } + } + ] + }, + "subscriptionAliasEnabled": { + "value": true + }, + "subscriptionAliasName": { + "value": "" + }, + "subscriptionBillingScope": { + "value": "" + }, + "subscriptionDisplayName": { + "value": "" + }, + "subscriptionManagementGroupAssociationEnabled": { + "value": true + }, + "subscriptionManagementGroupId": { + "value": "bicep-lz-vending-automation-child" + }, + "subscriptionTags": { + "value": { + "namePrefix": "", + "serviceShort": "" + } + }, + "subscriptionWorkload": { + "value": "Production" + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/lz/sub-vending:' + +param resourceProviders = {} +param roleAssignmentEnabled = true +param roleAssignments = [ + { + definition: '/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168' + principalId: '896b1162-be44-4b28-888a-d01acc1b4271' + relativeScope: '' + roleAssignmentCondition: { + roleConditionType: { + principleTypesToAssign: [ + 'Group' + 'ServicePrincipal' + ] + rolesToAssign: [ + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ] + templateName: 'constrainRolesAndPrincipalTypes' + } + } + } +] +param subscriptionAliasEnabled = true +param subscriptionAliasName = '' +param subscriptionBillingScope = '' +param subscriptionDisplayName = '' +param subscriptionManagementGroupAssociationEnabled = true +param subscriptionManagementGroupId = 'bicep-lz-vending-automation-child' +param subscriptionTags = { + namePrefix: '' + serviceShort: '' +} +param subscriptionWorkload = 'Production' +``` + +
+

+ +### Example 4: _Vwan topology._ This instance deploys a subscription with a vwan network topology. @@ -629,7 +796,7 @@ param virtualNetworkResourceGroupName = '' | [`roleAssignments`](#parameter-roleassignments) | array | Supply an array of objects containing the details of the role assignments to create.

Each object must contain the following `keys`:

  • `principalId` = The Object ID of the User, Group, SPN, Managed Identity to assign the RBAC role too.
  • `definition` = The Name of one of the pre-defined built-In RBAC Roles or a Resource ID of a Built-in or custom RBAC Role Definition as follows:

    - You can only provide the RBAC role name of the pre-defined roles (Contributor, Owner, Reader, Role Based Access Control Administrator (Preview), and User Access Administrator). We only provide those roles as they are the most common ones to assign to a new subscription, also to reduce the template size and complexity in case we define each and every Built-in RBAC role.

    - You can provide the Resource ID of a Built-in or custom RBAC Role Definition

    - e.g. `/providers/Microsoft.Authorization/roleDefinitions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`

  • `relativeScope` = 2 options can be provided for input value:

    1. `''` *(empty string)* = Make RBAC Role Assignment to Subscription scope

    2. `'/resourceGroups/'` = Make RBAC Role Assignment to specified Resource Group.

    | | [`subscriptionAliasEnabled`](#parameter-subscriptionaliasenabled) | bool | Whether to create a new Subscription using the Subscription Alias resource. If `false`, supply an existing Subscription''s ID in the parameter named `existingSubscriptionId` instead to deploy resources to an existing Subscription. | | [`subscriptionAliasName`](#parameter-subscriptionaliasname) | string | The name of the Subscription Alias, that will be created by this module.

    The string must be comprised of `a-z`, `A-Z`, `0-9`, `-`, `_` and ` ` (space). The maximum length is 63 characters.

    > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`**.

    | -| [`subscriptionBillingScope`](#parameter-subscriptionbillingscope) | string | The Billing Scope for the new Subscription alias, that will be created by this module.

    A valid Billing Scope starts with `/providers/Microsoft.Billing/billingAccounts/` and is case sensitive.

    > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`**.

    | +| [`subscriptionBillingScope`](#parameter-subscriptionbillingscope) | string | The Billing Scope for the new Subscription alias, that will be created by this module.

    A valid Billing Scope looks like `/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/enrollmentAccounts/{enrollmentAccountName}` and is case sensitive.

    > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`**.

    | | [`subscriptionDisplayName`](#parameter-subscriptiondisplayname) | string | The name of the subscription alias. The string must be comprised of a-z, A-Z, 0-9, - and _. The maximum length is 63 characters.

    The string must be comprised of `a-z`, `A-Z`, `0-9`, `-`, `_` and ` ` (space). The maximum length is 63 characters.

    > The value for this parameter and the parameter named `subscriptionAliasName` are usually set to the same value for simplicity. But they can be different if required for a reason.

    > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`**.

    | | [`subscriptionManagementGroupAssociationEnabled`](#parameter-subscriptionmanagementgroupassociationenabled) | bool | Whether to move the Subscription to the specified Management Group supplied in the parameter `subscriptionManagementGroupId`.

    | | [`subscriptionManagementGroupId`](#parameter-subscriptionmanagementgroupid) | string | The destination Management Group ID for the new Subscription that will be created by this module (or the existing one provided in the parameter `existingSubscriptionId`).

    **IMPORTANT:** Do not supply the display name of the Management Group. The Management Group ID forms part of the Azure Resource ID. e.g., `/providers/Microsoft.Management/managementGroups/{managementGroupId}`.

    | @@ -702,7 +869,7 @@ The name of the storage account for the deployment script. - Required: No - Type: string -- Default: `[format('stgds{0}', substring(uniqueString(deployment().name, parameters('virtualNetworkLocation')), 0, 4))]` +- Default: `[format('stgds{0}', substring(uniqueString(deployment().name, parameters('virtualNetworkLocation')), 0, 10))]` ### Parameter: `deploymentScriptVirtualNetworkName` @@ -816,7 +983,6 @@ An object of resource providers and resource providers features to register. If 'Microsoft.Sql': [] 'Microsoft.Storage': [] 'Microsoft.StreamAnalytics': [] - 'Microsoft.TimeSeriesInsights': [] 'Microsoft.Web': [] } ``` @@ -836,6 +1002,100 @@ Supply an array of objects containing the details of the role assignments to cre - Required: No - Type: array - Default: `[]` +- Example: + ```Bicep + [ + { + // Contributor role assignment at subscription scope + principalId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + definition: '/Contributor' + relativeScope: '' + } + { + // Owner role assignment at resource group scope + principalId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + definition: '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + relativeScope: '/resourceGroups/{resourceGroupName}' + } + ] + ``` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`definition`](#parameter-roleassignmentsdefinition) | string | The role definition ID or name. | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the user, group, or service principal. | +| [`relativeScope`](#parameter-roleassignmentsrelativescope) | string | The relative scope of the role assignment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`roleAssignmentCondition`](#parameter-roleassignmentsroleassignmentcondition) | object | The condition for the role assignment. | + +### Parameter: `roleAssignments.definition` + +The role definition ID or name. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.principalId` + +The principal ID of the user, group, or service principal. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.relativeScope` + +The relative scope of the role assignment. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleAssignmentCondition` + +The condition for the role assignment. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`conditionVersion`](#parameter-roleassignmentsroleassignmentconditionconditionversion) | string | The version of the condition template. | +| [`delegationCode`](#parameter-roleassignmentsroleassignmentconditiondelegationcode) | string | The code for a custom condition if no template is used. The user should supply their own custom code if the available templates are not matching their requirements. If a value is provided, this will overwrite any added template. All single quotes needs to be skipped using '. | +| [`roleConditionType`](#parameter-roleassignmentsroleassignmentconditionroleconditiontype) | object | The type of template for the role assignment condition. | + +### Parameter: `roleAssignments.roleAssignmentCondition.conditionVersion` + +The version of the condition template. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.roleAssignmentCondition.delegationCode` + +The code for a custom condition if no template is used. The user should supply their own custom code if the available templates are not matching their requirements. If a value is provided, this will overwrite any added template. All single quotes needs to be skipped using '. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.roleAssignmentCondition.roleConditionType` + +The type of template for the role assignment condition. + +- Required: No +- Type: object ### Parameter: `subscriptionAliasEnabled` @@ -855,7 +1115,7 @@ The name of the Subscription Alias, that will be created by this module.

    Th ### Parameter: `subscriptionBillingScope` -The Billing Scope for the new Subscription alias, that will be created by this module.

    A valid Billing Scope starts with `/providers/Microsoft.Billing/billingAccounts/` and is case sensitive.

    > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`**.

    +The Billing Scope for the new Subscription alias, that will be created by this module.

    A valid Billing Scope looks like `/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/enrollmentAccounts/{enrollmentAccountName}` and is case sensitive.

    > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`**.

    - Required: No - Type: string @@ -986,7 +1246,6 @@ The name of the virtual network. The string must consist of a-z, A-Z, 0-9, -, _, - Required: No - Type: string -- Default: `''` ### Parameter: `virtualNetworkPeeringEnabled` @@ -1085,10 +1344,10 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/ptn/authorization/role-assignment:0.1.0` | Remote reference | +| `br/public:avm/ptn/authorization/role-assignment:0.1.1` | Remote reference | | `br/public:avm/res/managed-identity/user-assigned-identity:0.2.2` | Remote reference | | `br/public:avm/res/network/network-security-group:0.3.0` | Remote reference | -| `br/public:avm/res/network/virtual-network:0.4.0` | Remote reference | +| `br/public:avm/res/network/virtual-network:0.5.0` | Remote reference | | `br/public:avm/res/resources/deployment-script:0.2.3` | Remote reference | | `br/public:avm/res/resources/resource-group:0.2.4` | Remote reference | | `br/public:avm/res/storage/storage-account:0.9.1` | Remote reference | diff --git a/avm/ptn/lz/sub-vending/main.bicep b/avm/ptn/lz/sub-vending/main.bicep index 62f27ca2c3..0511f295b5 100644 --- a/avm/ptn/lz/sub-vending/main.bicep +++ b/avm/ptn/lz/sub-vending/main.bicep @@ -9,6 +9,9 @@ This is the orchestration module that is used and called by a consumer of the mo targetScope = 'managementGroup' +//Imports +import { roleAssignmentType } from 'modules/subResourceWrapper.bicep' + // PARAMETERS // Subscription Parameters @@ -37,7 +40,7 @@ param subscriptionAliasName string = '' @description('''Optional. The Billing Scope for the new Subscription alias, that will be created by this module. -A valid Billing Scope starts with `/providers/Microsoft.Billing/billingAccounts/` and is case sensitive. +A valid Billing Scope looks like `/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/enrollmentAccounts/{enrollmentAccountName}` and is case sensitive. > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`**. ''') @@ -119,10 +122,11 @@ param virtualNetworkResourceGroupLockEnabled bool = true ''') param virtualNetworkLocation string = deployment().location +@minLength(2) @maxLength(64) @description('''Optional. The name of the virtual network. The string must consist of a-z, A-Z, 0-9, -, _, and . (period) and be between 2 and 64 characters in length. ''') -param virtualNetworkName string = '' +param virtualNetworkName string? @description('''Optional. An object of tag key/value pairs to be set on the Virtual Network that is created. @@ -196,9 +200,27 @@ Each object must contain the following `keys`: 1. `''` *(empty string)* = Make RBAC Role Assignment to Subscription scope 2. `'/resourceGroups/'` = Make RBAC Role Assignment to specified Resource Group. ''') -param roleAssignments array = [] +@metadata({ + example: ''' + [ + { + // Contributor role assignment at subscription scope + principalId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + definition: '/Contributor' + relativeScope: '' + } + { + // Owner role assignment at resource group scope + principalId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + definition: '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + relativeScope: '/resourceGroups/{resourceGroupName}' + } + ] + ''' +}) +param roleAssignments roleAssignmentType = [] -@sys.description('Optional. Enable/Disable usage telemetry for module.') +@description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true @description('Optional. The name of the resource group to create the deployment script for resource providers registration.') @@ -221,7 +243,7 @@ param deploymentScriptNetworkSecurityGroupName string = 'nsg-${deployment().loca param virtualNetworkDeploymentScriptAddressPrefix string = '192.168.0.0/24' @description('Optional. The name of the storage account for the deployment script.') -param deploymentScriptStorageAccountName string = 'stgds${substring(uniqueString(deployment().name, virtualNetworkLocation), 0, 4)}' +param deploymentScriptStorageAccountName string = 'stgds${substring(uniqueString(deployment().name, virtualNetworkLocation), 0, 10)}' @description('Optional. The location of the deployment script. Use region shortnames e.g. uksouth, eastus, etc.') param deploymentScriptLocation string = deployment().location @@ -293,7 +315,6 @@ param resourceProviders object = { 'Microsoft.Sql': [] 'Microsoft.Storage': [] 'Microsoft.StreamAnalytics': [] - 'Microsoft.TimeSeriesInsights': [] 'Microsoft.Web': [] } diff --git a/avm/ptn/lz/sub-vending/main.json b/avm/ptn/lz/sub-vending/main.json index ee24f61ead..3411c86bc6 100644 --- a/avm/ptn/lz/sub-vending/main.json +++ b/avm/ptn/lz/sub-vending/main.json @@ -1,17 +1,234 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2644636658214532574" + "version": "0.31.34.60546", + "templateHash": "5769743851515501504" }, "name": "Sub-vending", "description": "This module deploys a subscription to accelerate deployment of landing zones. For more information on how to use it, please visit this [Wiki](https://github.com/Azure/bicep-lz-vending/wiki).", "owner": "Azure/module-maintainers", "details": "These are the input parameters for the Bicep module: [`main.bicep`](./main.bicep)\n\nThis is the orchestration module that is used and called by a consumer of the module to deploy a Landing Zone Subscription and its associated resources, based on the parameter input values that are provided to it at deployment time.\n\n> For more information and examples please see the [wiki](https://github.com/Azure/bicep-lz-vending/wiki)" }, + "definitions": { + "_1.constrainedDelegationTemplatesType": { + "type": "object", + "discriminator": { + "propertyName": "templateName", + "mapping": { + "excludeRoles": { + "$ref": "#/definitions/_1.excludeRolesType" + }, + "constrainRoles": { + "$ref": "#/definitions/_1.constrainRolesType" + }, + "constrainRolesAndPrincipalTypes": { + "$ref": "#/definitions/_1.constrainRolesAndPrincipalTypesType" + }, + "constrainRolesAndPrincipals": { + "$ref": "#/definitions/_1.constrainRolesAndPrincipalsType" + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "modules/subResourceWrapper.bicep" + } + } + }, + "_1.constrainRolesAndPrincipalsType": { + "type": "object", + "properties": { + "templateName": { + "type": "string", + "allowedValues": [ + "constrainRolesAndPrincipals" + ], + "metadata": { + "description": "Required. Name of the RBAC condition template." + } + }, + "rolesToAssign": { + "type": "array", + "metadata": { + "description": "Required. The list of roles that are allowed to be assigned by the delegate." + } + }, + "principalsToAssignTo": { + "type": "array", + "metadata": { + "description": "Required. The list of principals that are allowed to be assigned roles by the delegate." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "modules/subResourceWrapper.bicep" + } + } + }, + "_1.constrainRolesAndPrincipalTypesType": { + "type": "object", + "properties": { + "templateName": { + "type": "string", + "allowedValues": [ + "constrainRolesAndPrincipalTypes" + ], + "metadata": { + "description": "Required. Name of the RBAC condition template." + } + }, + "rolesToAssign": { + "type": "array", + "metadata": { + "description": "Required. The list of roles that are allowed to be assigned by the delegate." + } + }, + "principleTypesToAssign": { + "type": "array", + "allowedValues": [ + "Group", + "ServicePrincipal", + "User" + ], + "metadata": { + "description": "Required. The list of principle types that are allowed to be assigned roles by the delegate." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "modules/subResourceWrapper.bicep" + } + } + }, + "_1.constrainRolesType": { + "type": "object", + "properties": { + "templateName": { + "type": "string", + "allowedValues": [ + "constrainRoles" + ], + "metadata": { + "description": "Required. Name of the RBAC condition template." + } + }, + "rolesToAssign": { + "type": "array", + "metadata": { + "description": "Required. The list of roles that are allowed to be assigned by the delegate." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "modules/subResourceWrapper.bicep" + } + } + }, + "_1.excludeRolesType": { + "type": "object", + "properties": { + "templateName": { + "type": "string", + "allowedValues": [ + "excludeRoles" + ], + "metadata": { + "description": "Required. Name of the RBAC condition template." + } + }, + "ExludededRoles": { + "type": "array", + "metadata": { + "description": "Required. The list of roles that are not allowed to be assigned by the delegate." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "modules/subResourceWrapper.bicep" + } + } + }, + "_1.roleAssignmentConditionType": { + "type": "object", + "properties": { + "roleConditionType": { + "$ref": "#/definitions/_1.constrainedDelegationTemplatesType", + "nullable": true, + "metadata": { + "description": "Optional. The type of template for the role assignment condition." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. The version of the condition template." + } + }, + "delegationCode": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The code for a custom condition if no template is used. The user should supply their own custom code if the available templates are not matching their requirements. If a value is provided, this will overwrite any added template. All single quotes needs to be skipped using '." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "modules/subResourceWrapper.bicep" + } + } + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the user, group, or service principal." + } + }, + "definition": { + "type": "string", + "metadata": { + "description": "Required. The role definition ID or name." + } + }, + "relativeScope": { + "type": "string", + "metadata": { + "description": "Required. The relative scope of the role assignment." + } + }, + "roleAssignmentCondition": { + "$ref": "#/definitions/_1.roleAssignmentConditionType", + "nullable": true, + "metadata": { + "description": "Optional. The condition for the role assignment." + } + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "modules/subResourceWrapper.bicep" + } + } + } + }, "parameters": { "subscriptionAliasEnabled": { "type": "bool", @@ -40,7 +257,7 @@ "type": "string", "defaultValue": "", "metadata": { - "description": "Optional. The Billing Scope for the new Subscription alias, that will be created by this module.\n\nA valid Billing Scope starts with `/providers/Microsoft.Billing/billingAccounts/` and is case sensitive.\n\n> **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`**.\n" + "description": "Optional. The Billing Scope for the new Subscription alias, that will be created by this module.\n\nA valid Billing Scope looks like `/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/enrollmentAccounts/{enrollmentAccountName}` and is case sensitive.\n\n> **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`**.\n" } }, "subscriptionWorkload": { @@ -137,7 +354,8 @@ }, "virtualNetworkName": { "type": "string", - "defaultValue": "", + "nullable": true, + "minLength": 2, "maxLength": 64, "metadata": { "description": "Optional. The name of the virtual network. The string must consist of a-z, A-Z, 0-9, -, _, and . (period) and be between 2 and 64 characters in length.\n" @@ -235,9 +453,10 @@ } }, "roleAssignments": { - "type": "array", + "$ref": "#/definitions/roleAssignmentType", "defaultValue": [], "metadata": { + "example": " [\n {\n // Contributor role assignment at subscription scope\n principalId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'\n definition: '/Contributor'\n relativeScope: ''\n }\n {\n // Owner role assignment at resource group scope\n principalId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'\n definition: '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635'\n relativeScope: '/resourceGroups/{resourceGroupName}'\n }\n ]\n ", "description": "Optional. Supply an array of objects containing the details of the role assignments to create.\n\nEach object must contain the following `keys`:\n- `principalId` = The Object ID of the User, Group, SPN, Managed Identity to assign the RBAC role too.\n- `definition` = The Name of one of the pre-defined built-In RBAC Roles or a Resource ID of a Built-in or custom RBAC Role Definition as follows:\n - You can only provide the RBAC role name of the pre-defined roles (Contributor, Owner, Reader, Role Based Access Control Administrator (Preview), and User Access Administrator). We only provide those roles as they are the most common ones to assign to a new subscription, also to reduce the template size and complexity in case we define each and every Built-in RBAC role.\n - You can provide the Resource ID of a Built-in or custom RBAC Role Definition\n - e.g. `/providers/Microsoft.Authorization/roleDefinitions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`\n- `relativeScope` = 2 options can be provided for input value:\n 1. `''` *(empty string)* = Make RBAC Role Assignment to Subscription scope\n 2. `'/resourceGroups/'` = Make RBAC Role Assignment to specified Resource Group.\n" } }, @@ -293,7 +512,7 @@ }, "deploymentScriptStorageAccountName": { "type": "string", - "defaultValue": "[format('stgds{0}', substring(uniqueString(deployment().name, parameters('virtualNetworkLocation')), 0, 4))]", + "defaultValue": "[format('stgds{0}', substring(uniqueString(deployment().name, parameters('virtualNetworkLocation')), 0, 10))]", "metadata": { "description": "Optional. The name of the storage account for the deployment script." } @@ -371,7 +590,6 @@ "Microsoft.Sql": [], "Microsoft.Storage": [], "Microsoft.StreamAnalytics": [], - "Microsoft.TimeSeriesInsights": [], "Microsoft.Web": [] }, "metadata": { @@ -393,8 +611,8 @@ "createSubscriptionResources": "[take(format('lz-vend-sub-res-create-{0}-{1}', parameters('subscriptionAliasName'), uniqueString(parameters('subscriptionAliasName'), parameters('subscriptionDisplayName'), parameters('subscriptionBillingScope'), parameters('subscriptionWorkload'), parameters('existingSubscriptionId'), deployment().name)), 64)]" } }, - "resources": [ - { + "resources": { + "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", @@ -415,7 +633,7 @@ } } }, - { + "createSubscription": { "condition": "[and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -452,8 +670,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "1611270751895734589" + "version": "0.31.34.60546", + "templateHash": "3457070988046201960" } }, "parameters": { @@ -540,7 +758,7 @@ } } }, - { + "createSubscriptionResources": { "condition": "[or(parameters('subscriptionAliasEnabled'), not(empty(parameters('existingSubscriptionId'))))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -552,7 +770,7 @@ }, "mode": "Incremental", "parameters": { - "subscriptionId": "[if(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), createObject('value', reference(extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', variables('deploymentNames').createSubscription), '2022-09-01').outputs.subscriptionId.value), createObject('value', parameters('existingSubscriptionId')))]", + "subscriptionId": "[if(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), createObject('value', reference('createSubscription').outputs.subscriptionId.value), createObject('value', parameters('existingSubscriptionId')))]", "managementGroupAssociationDelayCount": { "value": "[parameters('managementGroupAssociationDelayCount')]" }, @@ -658,111 +876,415 @@ }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2549730186599602050" + "version": "0.31.34.60546", + "templateHash": "15704136472131684900" }, "name": "`/subResourcesWrapper/deploy.bicep` Parameters", "description": "This module is used by the [`bicep-lz-vending`](https://aka.ms/sub-vending/bicep) module to help orchestrate the deployment", "details": "These are the input parameters for the Bicep module: [`deploy.bicep`](./deploy.bicep)\n\nThis is the sub-orchestration module that is used and called by the [`main.bicep`](../../../main.bicep) module to deploy the resources into the subscription that has been created (or an existing one provided), based on the parameter input values that are provided to it at deployment time from the `main.bicep` orchestration module.\n\n> ⚠️ It is not intended for this module to be called outside of being a sub-orchestration module for the `main.bicep` module ⚠️" }, - "parameters": { - "subscriptionId": { - "type": "string", - "maxLength": 36 - }, - "subscriptionManagementGroupAssociationEnabled": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Whether to move the subscription to the specified management group supplied in the pararmeter subscriptionManagementGroupId." - } - }, - "subscriptionManagementGroupId": { - "type": "string", - "defaultValue": "", + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the user, group, or service principal." + } + }, + "definition": { + "type": "string", + "metadata": { + "description": "Required. The role definition ID or name." + } + }, + "relativeScope": { + "type": "string", + "metadata": { + "description": "Required. The relative scope of the role assignment." + } + }, + "roleAssignmentCondition": { + "$ref": "#/definitions/roleAssignmentConditionType", + "nullable": true, + "metadata": { + "description": "Optional. The condition for the role assignment." + } + } + } + }, "metadata": { - "description": "The destination management group ID for the new subscription. Note: Do not supply the display name. The management group ID forms part of the Azure resource ID. e.g., `/providers/Microsoft.Management/managementGroups/{managementGroupId}`." + "__bicep_export!": true } }, - "subscriptionTags": { + "constrainRolesType": { "type": "object", - "defaultValue": {}, - "metadata": { - "description": "An object of tag key/value pairs to be appended to a subscription. NOTE: Tags will only be overwriten if existing tag exists with same key; values provided here win." - } - }, - "virtualNetworkEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Whether to create a virtual network or not." - } - }, - "virtualNetworkResourceGroupName": { - "type": "string", - "defaultValue": "", - "maxLength": 90, - "metadata": { - "description": "The name of the resource group to create the virtual network in." - } - }, - "virtualNetworkResourceGroupLockEnabled": { - "type": "bool", - "defaultValue": true, + "properties": { + "templateName": { + "type": "string", + "allowedValues": [ + "constrainRoles" + ], + "metadata": { + "description": "Required. Name of the RBAC condition template." + } + }, + "rolesToAssign": { + "type": "array", + "metadata": { + "description": "Required. The list of roles that are allowed to be assigned by the delegate." + } + } + }, "metadata": { - "description": "Enables the deployment of a `CanNotDelete` resource locks to the virtual networks resource group." + "__bicep_export!": true } }, - "virtualNetworkResourceGroupTags": { + "constrainRolesAndPrincipalTypesType": { "type": "object", - "defaultValue": {}, - "metadata": { - "description": "An object of tag key/value pairs to be appended to the Resource Group that the Virtual Network is created in. NOTE: Tags will only be overwriten if existing tag exists with same key; values provided here win." - } - }, - "virtualNetworkLocation": { - "type": "string", - "defaultValue": "[deployment().location]", + "properties": { + "templateName": { + "type": "string", + "allowedValues": [ + "constrainRolesAndPrincipalTypes" + ], + "metadata": { + "description": "Required. Name of the RBAC condition template." + } + }, + "rolesToAssign": { + "type": "array", + "metadata": { + "description": "Required. The list of roles that are allowed to be assigned by the delegate." + } + }, + "principleTypesToAssign": { + "type": "array", + "allowedValues": [ + "Group", + "ServicePrincipal", + "User" + ], + "metadata": { + "description": "Required. The list of principle types that are allowed to be assigned roles by the delegate." + } + } + }, "metadata": { - "description": "The location of the virtual network. Use region shortnames e.g. uksouth, eastus, etc." + "__bicep_export!": true } }, - "virtualNetworkName": { - "type": "string", - "defaultValue": "", - "maxLength": 64, + "constrainRolesAndPrincipalsType": { + "type": "object", + "properties": { + "templateName": { + "type": "string", + "allowedValues": [ + "constrainRolesAndPrincipals" + ], + "metadata": { + "description": "Required. Name of the RBAC condition template." + } + }, + "rolesToAssign": { + "type": "array", + "metadata": { + "description": "Required. The list of roles that are allowed to be assigned by the delegate." + } + }, + "principalsToAssignTo": { + "type": "array", + "metadata": { + "description": "Required. The list of principals that are allowed to be assigned roles by the delegate." + } + } + }, "metadata": { - "description": "The name of the virtual network. The string must consist of a-z, A-Z, 0-9, -, _, and . (period) and be between 2 and 64 characters in length." + "__bicep_export!": true } }, - "virtualNetworkTags": { + "excludeRolesType": { "type": "object", - "defaultValue": {}, + "properties": { + "templateName": { + "type": "string", + "allowedValues": [ + "excludeRoles" + ], + "metadata": { + "description": "Required. Name of the RBAC condition template." + } + }, + "ExludededRoles": { + "type": "array", + "metadata": { + "description": "Required. The list of roles that are not allowed to be assigned by the delegate." + } + } + }, "metadata": { - "description": "An object of tag key/value pairs to be set on the Virtual Network that is created. NOTE: Tags will be overwritten on resoruce if any exist already." + "__bicep_export!": true } }, - "virtualNetworkAddressSpace": { - "type": "array", - "defaultValue": [], + "constrainedDelegationTemplatesType": { + "type": "object", + "discriminator": { + "propertyName": "templateName", + "mapping": { + "excludeRoles": { + "$ref": "#/definitions/excludeRolesType" + }, + "constrainRoles": { + "$ref": "#/definitions/constrainRolesType" + }, + "constrainRolesAndPrincipalTypes": { + "$ref": "#/definitions/constrainRolesAndPrincipalTypesType" + }, + "constrainRolesAndPrincipals": { + "$ref": "#/definitions/constrainRolesAndPrincipalsType" + } + } + }, "metadata": { - "description": "The address space of the virtual network, supplied as multiple CIDR blocks, e.g. `[\"10.0.0.0/16\",\"172.16.0.0/12\"]`" + "__bicep_export!": true } }, - "virtualNetworkDnsServers": { - "type": "array", - "defaultValue": [], + "roleAssignmentConditionType": { + "type": "object", + "properties": { + "roleConditionType": { + "$ref": "#/definitions/constrainedDelegationTemplatesType", + "nullable": true, + "metadata": { + "description": "Optional. The type of template for the role assignment condition." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. The version of the condition template." + } + }, + "delegationCode": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The code for a custom condition if no template is used. The user should supply their own custom code if the available templates are not matching their requirements. If a value is provided, this will overwrite any added template. All single quotes needs to be skipped using '." + } + } + }, "metadata": { - "description": "The custom DNS servers to use on the virtual network, e.g. `[\"10.4.1.4\", \"10.2.1.5\"]. If left empty (default) then Azure DNS will be used for the virtual network.`" + "__bicep_export!": true } - }, - "virtualNetworkDdosPlanResourceId": { - "type": "string", - "defaultValue": "", + } + }, + "functions": [ + { + "namespace": "__bicep", + "members": { + "generateCodeRolesType": { + "parameters": [ + { + "$ref": "#/definitions/constrainRolesType", + "name": "constrainRoles" + } + ], + "output": { + "type": "string", + "value": "[format('((!(ActionMatches{{''Microsoft.Authorization/roleAssignments/write''}})) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {{{0}}}) AND ((!(ActionMatches{{''Microsoft.Authorization/roleAssignments/delete''}}) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {{{1}}}))))', __bicep.joinArray(parameters('constrainRoles').rolesToAssign), __bicep.joinArray(parameters('constrainRoles').rolesToAssign))]" + }, + "metadata": { + "description": "Generates the code for the \"Constrain Roles\" condition template.", + "__bicep_export!": true + } + }, + "generateCodeRolesAndPrincipalsTypes": { + "parameters": [ + { + "$ref": "#/definitions/constrainRolesAndPrincipalTypesType", + "name": "constrainRolesAndPrincipalsTypes" + } + ], + "output": { + "type": "string", + "value": "[format('((!(ActionMatches{{''Microsoft.Authorization/roleAssignments/write''}}) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {{{0}}} AND @Request[Microsoft.Authorization/roleAssignments:PrincipalType] ForAnyOfAnyValues:StringEqualsIgnoreCase {{{1}}})) AND ((!(ActionMatches{{''Microsoft.Authorization/roleAssignments/delete''}})) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {{{2}}} AND @Resource[Microsoft.Authorization/roleAssignments:PrincipalType] ForAnyOfAnyValues:StringEqualsIgnoreCase {{{3}}})))', __bicep.joinArray(parameters('constrainRolesAndPrincipalsTypes').rolesToAssign), __bicep.joinArrayIgnoreCase(parameters('constrainRolesAndPrincipalsTypes').principleTypesToAssign), __bicep.joinArray(parameters('constrainRolesAndPrincipalsTypes').rolesToAssign), __bicep.joinArrayIgnoreCase(parameters('constrainRolesAndPrincipalsTypes').principleTypesToAssign))]" + }, + "metadata": { + "description": "Generates the code for the \"Constrain Roles and Principal types\" condition template.", + "__bicep_export!": true + } + }, + "generateCodeRolesAndPrincipals": { + "parameters": [ + { + "$ref": "#/definitions/constrainRolesAndPrincipalsType", + "name": "constrainRolesAndPrincipals" + } + ], + "output": { + "type": "string", + "value": "[format('((!(ActionMatches{{''Microsoft.Authorization/roleAssignments/write''}}) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {{{0}}} AND @Request[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {{{1}}})) AND ((!(ActionMatches{{''Microsoft.Authorization/roleAssignments/delete''}})) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {{{2}}} AND @Resource[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {{{3}}})))', __bicep.joinArray(parameters('constrainRolesAndPrincipals').rolesToAssign), __bicep.joinArray(parameters('constrainRolesAndPrincipals').principalsToAssignTo), __bicep.joinArray(parameters('constrainRolesAndPrincipals').rolesToAssign), __bicep.joinArray(parameters('constrainRolesAndPrincipals').principalsToAssignTo))]" + }, + "metadata": { + "description": "Generates the code for the \"Constrain Roles and Principals\" condition template.", + "__bicep_export!": true + } + }, + "generateCodeExcludeRoles": { + "parameters": [ + { + "$ref": "#/definitions/excludeRolesType", + "name": "excludeRoles" + } + ], + "output": { + "type": "string", + "value": "[format('((!(ActionMatches{{''Microsoft.Authorization/roleAssignments/write''}}) OR ( @Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAllValues:GuidNotEquals {{{0}}})) AND ((!(ActionMatches{{''Microsoft.Authorization/roleAssignments/delete''}}) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAllValues:GuidNotEquals {{{1}}}))))', __bicep.joinArray(parameters('excludeRoles').ExludededRoles), __bicep.joinArray(parameters('excludeRoles').ExludededRoles))]" + }, + "metadata": { + "description": "Generates the code for the \"Exclude Roles\" condition template.", + "__bicep_export!": true + } + }, + "joinArray": { + "parameters": [ + { + "type": "array", + "name": "roles" + } + ], + "output": { + "type": "string", + "value": "[replace(join(parameters('roles'), ','), '\"', '')]" + }, + "metadata": { + "__bicep_export!": true + } + }, + "joinArrayIgnoreCase": { + "parameters": [ + { + "type": "array", + "name": "principalTypes" + } + ], + "output": { + "type": "string", + "value": "[format('''{0}''', replace(replace(join(parameters('principalTypes'), ','), '\"', ''''), ',', ''','''))]" + }, + "metadata": { + "__bicep_export!": true + } + } + } + } + ], + "parameters": { + "subscriptionId": { + "type": "string", + "maxLength": 36 + }, + "subscriptionManagementGroupAssociationEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Whether to move the subscription to the specified management group supplied in the pararmeter subscriptionManagementGroupId." + } + }, + "subscriptionManagementGroupId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The destination management group ID for the new subscription. Note: Do not supply the display name. The management group ID forms part of the Azure resource ID. e.g., `/providers/Microsoft.Management/managementGroups/{managementGroupId}`." + } + }, + "subscriptionTags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "An object of tag key/value pairs to be appended to a subscription. NOTE: Tags will only be overwriten if existing tag exists with same key; values provided here win." + } + }, + "virtualNetworkEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Whether to create a virtual network or not." + } + }, + "virtualNetworkResourceGroupName": { + "type": "string", + "defaultValue": "", + "maxLength": 90, + "metadata": { + "description": "The name of the resource group to create the virtual network in." + } + }, + "virtualNetworkResourceGroupLockEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Enables the deployment of a `CanNotDelete` resource locks to the virtual networks resource group." + } + }, + "virtualNetworkResourceGroupTags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "An object of tag key/value pairs to be appended to the Resource Group that the Virtual Network is created in. NOTE: Tags will only be overwriten if existing tag exists with same key; values provided here win." + } + }, + "virtualNetworkLocation": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "The location of the virtual network. Use region shortnames e.g. uksouth, eastus, etc." + } + }, + "virtualNetworkName": { + "type": "string", + "defaultValue": "", + "maxLength": 64, + "metadata": { + "description": "The name of the virtual network. The string must consist of a-z, A-Z, 0-9, -, _, and . (period) and be between 2 and 64 characters in length." + } + }, + "virtualNetworkTags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "An object of tag key/value pairs to be set on the Virtual Network that is created. NOTE: Tags will be overwritten on resoruce if any exist already." + } + }, + "virtualNetworkAddressSpace": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "The address space of the virtual network, supplied as multiple CIDR blocks, e.g. `[\"10.0.0.0/16\",\"172.16.0.0/12\"]`" + } + }, + "virtualNetworkDnsServers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "The custom DNS servers to use on the virtual network, e.g. `[\"10.4.1.4\", \"10.2.1.5\"]. If left empty (default) then Azure DNS will be used for the virtual network.`" + } + }, + "virtualNetworkDdosPlanResourceId": { + "type": "string", + "defaultValue": "", "metadata": { "description": "The resoruce ID of an existing DDoS Network Protection Plan that you wish to link to this virtual network." } @@ -831,7 +1353,7 @@ } }, "roleAssignments": { - "type": "array", + "$ref": "#/definitions/roleAssignmentType", "defaultValue": [], "metadata": { "description": "Supply an array of objects containing the details of the role assignments to create." @@ -952,7 +1474,6 @@ "Microsoft.Sql": [], "Microsoft.Storage": [], "Microsoft.StreamAnalytics": [], - "Microsoft.TimeSeriesInsights": [], "Microsoft.Web": [] }, "metadata": { @@ -1019,8 +1540,8 @@ "virtualWanHubConnectionPropogatedLabels": "[if(not(empty(parameters('virtualNetworkVwanPropagatedLabels'))), parameters('virtualNetworkVwanPropagatedLabels'), createArray('default'))]", "resourceProvidersFormatted": "[replace(string(parameters('resourceProviders')), '\"', '\\\"')]" }, - "resources": [ - { + "resources": { + "moveSubscriptionToManagementGroupDelay": { "copy": { "name": "moveSubscriptionToManagementGroupDelay", "count": "[length(range(0, parameters('managementGroupAssociationDelayCount')))]", @@ -1041,7 +1562,7 @@ } } }, - { + "moveSubscriptionToManagementGroup": { "condition": "[and(parameters('subscriptionManagementGroupAssociationEnabled'), not(empty(parameters('subscriptionManagementGroupId'))))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -1067,8 +1588,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "15074465703139369012" + "version": "0.31.34.60546", + "templateHash": "17907165258968798055" } }, "parameters": { @@ -1099,7 +1620,7 @@ "moveSubscriptionToManagementGroupDelay" ] }, - { + "tagSubscription": { "condition": "[not(empty(parameters('subscriptionTags')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -1128,8 +1649,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "15410141635305926698" + "version": "0.31.34.60546", + "templateHash": "3960537387423914398" } }, "parameters": { @@ -1188,8 +1709,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "5472979603320584709" + "version": "0.31.34.60546", + "templateHash": "4908789287090218941" } }, "parameters": { @@ -1244,8 +1765,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11343593259864722989" + "version": "0.31.34.60546", + "templateHash": "12493928637555451452" } }, "parameters": { @@ -1322,8 +1843,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13884963778440627255" + "version": "0.31.34.60546", + "templateHash": "12602325500495654095" } }, "parameters": { @@ -1377,8 +1898,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4428652978548820109" + "version": "0.31.34.60546", + "templateHash": "7409476431103411951" } }, "parameters": { @@ -1464,7 +1985,7 @@ } } }, - { + "createResourceGroupForLzNetworking": { "condition": "[and(and(parameters('virtualNetworkEnabled'), not(empty(parameters('virtualNetworkLocation')))), not(empty(parameters('virtualNetworkResourceGroupName'))))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -1925,7 +2446,7 @@ } } }, - { + "tagResourceGroup": { "condition": "[and(and(and(parameters('virtualNetworkEnabled'), not(empty(parameters('virtualNetworkLocation')))), not(empty(parameters('virtualNetworkResourceGroupName')))), not(empty(parameters('virtualNetworkResourceGroupTags'))))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -1957,8 +2478,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "15410141635305926698" + "version": "0.31.34.60546", + "templateHash": "3960537387423914398" } }, "parameters": { @@ -2017,8 +2538,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "5472979603320584709" + "version": "0.31.34.60546", + "templateHash": "4908789287090218941" } }, "parameters": { @@ -2073,8 +2594,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11343593259864722989" + "version": "0.31.34.60546", + "templateHash": "12493928637555451452" } }, "parameters": { @@ -2151,8 +2672,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13884963778440627255" + "version": "0.31.34.60546", + "templateHash": "12602325500495654095" } }, "parameters": { @@ -2206,8 +2727,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4428652978548820109" + "version": "0.31.34.60546", + "templateHash": "7409476431103411951" } }, "parameters": { @@ -2293,10 +2814,10 @@ } }, "dependsOn": [ - "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Resources/deployments', variables('deploymentNames').createResourceGroupForLzNetworking)]" + "createResourceGroupForLzNetworking" ] }, - { + "createLzVnet": { "condition": "[and(and(and(and(parameters('virtualNetworkEnabled'), not(empty(parameters('virtualNetworkName')))), not(empty(parameters('virtualNetworkAddressSpace')))), not(empty(parameters('virtualNetworkLocation')))), not(empty(parameters('virtualNetworkResourceGroupName'))))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -2339,260 +2860,42 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15949466154563447171" + "version": "0.30.23.60470", + "templateHash": "12023193036665775110" }, "name": "Virtual Networks", "description": "This module deploys a Virtual Network (vNet).", "owner": "Azure/module-maintainers" }, "definitions": { - "lockType": { + "peeringType": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. The Name of VNET Peering resource. If not provided, default value will be peer-localVnetName-remoteVnetName." } }, - "kind": { + "remoteVirtualNetworkResourceId": { "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], + "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", "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "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." } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } - } - } - }, - "nullable": true - }, - "peeringType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Name of VNET Peering resource. If not provided, default value will be peer-localVnetName-remoteVnetName." - } - }, - "remoteVirtualNetworkResourceId": { - "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", - "nullable": 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", - "nullable": true, - "metadata": { - "description": "Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false." + }, + "allowGatewayTransit": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false." } }, "allowVirtualNetworkAccess": { @@ -2727,9 +3030,10 @@ "privateEndpointNetworkPolicies": { "type": "string", "allowedValues": [ - "", "Disabled", - "Enabled" + "Enabled", + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" ], "nullable": true, "metadata": { @@ -2739,7 +3043,6 @@ "privateLinkServiceNetworkPolicies": { "type": "string", "allowedValues": [ - "", "Disabled", "Enabled" ], @@ -2749,7 +3052,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -2800,25 +3107,252 @@ } } } - } - }, - "parameters": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the Virtual Network (vNet)." - } }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, "metadata": { - "description": "Optional. Location for all resources." + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } } }, - "addressPrefixes": { - "type": "array", - "metadata": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Virtual Network (vNet)." + } + }, + "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." } }, @@ -2893,19 +3427,28 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -2954,7 +3497,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.network-virtualnetwork.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-virtualnetwork.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -3138,8 +3681,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5699372618313647761" + "version": "0.30.23.60470", + "templateHash": "6411714881793832751" }, "name": "Virtual Network Subnets", "description": "This module deploys a Virtual Network Subnet.", @@ -3147,77 +3690,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } } }, "parameters": { @@ -3280,11 +3825,12 @@ }, "privateEndpointNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", "Enabled", - "" + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private endpoint in the subnet." @@ -3292,11 +3838,10 @@ }, "privateLinkServiceNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", - "Enabled", - "" + "Enabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private link service in the subnet." @@ -3345,7 +3890,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -3395,8 +3944,8 @@ "routeTable": "[if(not(empty(parameters('routeTableResourceId'))), createObject('id', parameters('routeTableResourceId')), null())]", "natGateway": "[if(not(empty(parameters('natGatewayResourceId'))), createObject('id', parameters('natGatewayResourceId')), null())]", "delegations": "[if(not(empty(parameters('delegation'))), createArray(createObject('name', parameters('delegation'), 'properties', createObject('serviceName', parameters('delegation')))), createArray())]", - "privateEndpointNetworkPolicies": "[if(not(empty(parameters('privateEndpointNetworkPolicies'))), parameters('privateEndpointNetworkPolicies'), null())]", - "privateLinkServiceNetworkPolicies": "[if(not(empty(parameters('privateLinkServiceNetworkPolicies'))), parameters('privateLinkServiceNetworkPolicies'), null())]", + "privateEndpointNetworkPolicies": "[parameters('privateEndpointNetworkPolicies')]", + "privateLinkServiceNetworkPolicies": "[parameters('privateLinkServiceNetworkPolicies')]", "applicationGatewayIPConfigurations": "[parameters('applicationGatewayIPConfigurations')]", "serviceEndpointPolicies": "[parameters('serviceEndpointPolicies')]", "defaultOutboundAccess": "[parameters('defaultOutboundAccess')]", @@ -3517,8 +4066,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5206620163504251868" + "version": "0.30.23.60470", + "templateHash": "345394220621166229" }, "name": "Virtual Network Peerings", "description": "This module deploys a Virtual Network Peering.", @@ -3623,7 +4172,8 @@ } }, "dependsOn": [ - "virtualNetwork" + "virtualNetwork", + "virtualNetwork_subnets" ] }, "virtualNetwork_peering_remote": { @@ -3674,8 +4224,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5206620163504251868" + "version": "0.30.23.60470", + "templateHash": "345394220621166229" }, "name": "Virtual Network Peerings", "description": "This module deploys a Virtual Network Peering.", @@ -3780,7 +4330,8 @@ } }, "dependsOn": [ - "virtualNetwork" + "virtualNetwork", + "virtualNetwork_subnets" ] } }, @@ -3837,10 +4388,10 @@ } }, "dependsOn": [ - "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Resources/deployments', variables('deploymentNames').createResourceGroupForLzNetworking)]" + "createResourceGroupForLzNetworking" ] }, - { + "createLzVirtualWanConnection": { "condition": "[and(and(and(and(and(and(and(and(parameters('virtualNetworkEnabled'), parameters('virtualNetworkPeeringEnabled')), not(empty(variables('virtualHubResourceIdChecked')))), not(empty(parameters('virtualNetworkName')))), not(empty(parameters('virtualNetworkAddressSpace')))), not(empty(parameters('virtualNetworkLocation')))), not(empty(parameters('virtualNetworkResourceGroupName')))), not(empty(variables('virtualWanHubResourceGroupName')))), not(empty(variables('virtualWanHubSubscriptionId'))))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -3873,8 +4424,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "15250207882926040999" + "version": "0.31.34.60546", + "templateHash": "11117025288711367178" } }, "parameters": { @@ -3951,11 +4502,11 @@ } }, "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('virtualNetworkResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createLzVnet)]", - "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Resources/deployments', variables('deploymentNames').createResourceGroupForLzNetworking)]" + "createLzVnet", + "createResourceGroupForLzNetworking" ] }, - { + "createLzRoleAssignmentsSub": { "copy": { "name": "createLzRoleAssignmentsSub", "count": "[length(variables('roleAssignmentsSubscription'))]" @@ -3982,7 +4533,9 @@ }, "subscriptionId": { "value": "[parameters('subscriptionId')]" - } + }, + "conditionVersion": "[if(not(empty(coalesce(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), createObject()))), createObject('value', coalesce(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'conditionVersion'), '2.0')), createObject('value', null()))]", + "condition": "[if(empty(coalesce(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), createObject())), createObject('value', null()), if(and(equals(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'constrainRoles'), empty(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeRolesType(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(and(equals(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'constrainRolesAndPrincipalTypes'), empty(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeRolesAndPrincipalsTypes(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(and(equals(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'constrainRolesAndPrincipals'), empty(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeRolesAndPrincipals(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(and(equals(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'excludeRoles'), empty(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeExcludeRoles(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(not(empty(tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', tryGet(tryGet(variables('roleAssignmentsSubscription')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode')), createObject('value', null())))))))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#", @@ -3990,8 +4543,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4635601566143603046" + "version": "0.28.1.47646", + "templateHash": "4097241605548087035" }, "name": "Role Assignments (All scopes)", "description": "This module deploys a Role Assignment at a Management Group, Subscription or Resource Group scope.", @@ -4096,8 +4649,8 @@ { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -4150,8 +4703,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "13749459126745145624" + "version": "0.28.1.47646", + "templateHash": "8906093264527258150" }, "name": "Role Assignments (Management Group scope)", "description": "This module deploys a Role Assignment at a Management Group scope.", @@ -4314,8 +4867,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4516670639800961845" + "version": "0.28.1.47646", + "templateHash": "707244099707019442" }, "name": "Role Assignments (Subscription scope)", "description": "This module deploys a Role Assignment at a Subscription scope.", @@ -4486,8 +5039,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "7241874480439813582" + "version": "0.28.1.47646", + "templateHash": "14591941439222880522" }, "name": "Role Assignments (Resource Group scope)", "description": "This module deploys a Role Assignment at a Resource Group scope.", @@ -4652,7 +5205,7 @@ } } }, - { + "createLzRoleAssignmentsRsgsSelf": { "copy": { "name": "createLzRoleAssignmentsRsgsSelf", "count": "[length(variables('roleAssignmentsResourceGroupSelf'))]" @@ -4682,7 +5235,9 @@ }, "resourceGroupName": { "value": "[split(variables('roleAssignmentsResourceGroupSelf')[copyIndex()].relativeScope, '/')[2]]" - } + }, + "conditionVersion": "[if(not(empty(coalesce(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), createObject()))), createObject('value', coalesce(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'conditionVersion'), '2.0')), createObject('value', null()))]", + "condition": "[if(empty(coalesce(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), createObject())), createObject('value', null()), if(and(equals(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'constrainRoles'), empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeRolesType(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(and(equals(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'constrainRolesAndPrincipalTypes'), empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeRolesAndPrincipalsTypes(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(and(equals(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'constrainRolesAndPrincipals'), empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeRolesAndPrincipals(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(and(equals(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'excludeRoles'), empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeExcludeRoles(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(not(empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', tryGet(tryGet(variables('roleAssignmentsResourceGroupSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode')), createObject('value', null())))))))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#", @@ -4690,8 +5245,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4635601566143603046" + "version": "0.28.1.47646", + "templateHash": "4097241605548087035" }, "name": "Role Assignments (All scopes)", "description": "This module deploys a Role Assignment at a Management Group, Subscription or Resource Group scope.", @@ -4796,8 +5351,8 @@ { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -4850,8 +5405,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "13749459126745145624" + "version": "0.28.1.47646", + "templateHash": "8906093264527258150" }, "name": "Role Assignments (Management Group scope)", "description": "This module deploys a Role Assignment at a Management Group scope.", @@ -5014,8 +5569,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4516670639800961845" + "version": "0.28.1.47646", + "templateHash": "707244099707019442" }, "name": "Role Assignments (Subscription scope)", "description": "This module deploys a Role Assignment at a Subscription scope.", @@ -5186,8 +5741,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "7241874480439813582" + "version": "0.28.1.47646", + "templateHash": "14591941439222880522" }, "name": "Role Assignments (Resource Group scope)", "description": "This module deploys a Role Assignment at a Resource Group scope.", @@ -5352,10 +5907,10 @@ } }, "dependsOn": [ - "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Resources/deployments', variables('deploymentNames').createResourceGroupForLzNetworking)]" + "createResourceGroupForLzNetworking" ] }, - { + "createLzRoleAssignmentsRsgsNotSelf": { "copy": { "name": "createLzRoleAssignmentsRsgsNotSelf", "count": "[length(variables('roleAssignmentsResourceGroupNotSelf'))]" @@ -5385,7 +5940,9 @@ }, "resourceGroupName": { "value": "[split(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()].relativeScope, '/')[2]]" - } + }, + "conditionVersion": "[if(not(empty(coalesce(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), createObject()))), createObject('value', coalesce(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'conditionVersion'), '2.0')), createObject('value', null()))]", + "condition": "[if(empty(coalesce(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), createObject())), createObject('value', null()), if(and(equals(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'constrainRoles'), empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeRolesType(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(and(equals(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'constrainRolesAndPrincipalTypes'), empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeRolesAndPrincipalsTypes(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(and(equals(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'constrainRolesAndPrincipals'), empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeRolesAndPrincipals(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(and(equals(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType', 'templateName'), 'excludeRoles'), empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', __bicep.generateCodeExcludeRoles(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'roleConditionType'))), if(not(empty(tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode'))), createObject('value', tryGet(tryGet(variables('roleAssignmentsResourceGroupNotSelf')[copyIndex()], 'roleAssignmentCondition'), 'delegationCode')), createObject('value', null())))))))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#", @@ -5393,8 +5950,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4635601566143603046" + "version": "0.28.1.47646", + "templateHash": "4097241605548087035" }, "name": "Role Assignments (All scopes)", "description": "This module deploys a Role Assignment at a Management Group, Subscription or Resource Group scope.", @@ -5499,8 +6056,8 @@ { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -5553,8 +6110,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "13749459126745145624" + "version": "0.28.1.47646", + "templateHash": "8906093264527258150" }, "name": "Role Assignments (Management Group scope)", "description": "This module deploys a Role Assignment at a Management Group scope.", @@ -5717,8 +6274,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4516670639800961845" + "version": "0.28.1.47646", + "templateHash": "707244099707019442" }, "name": "Role Assignments (Subscription scope)", "description": "This module deploys a Role Assignment at a Subscription scope.", @@ -5889,8 +6446,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "7241874480439813582" + "version": "0.28.1.47646", + "templateHash": "14591941439222880522" }, "name": "Role Assignments (Resource Group scope)", "description": "This module deploys a Role Assignment at a Resource Group scope.", @@ -6055,7 +6612,7 @@ } } }, - { + "createResourceGroupForDeploymentScript": { "condition": "[not(empty(parameters('resourceProviders')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -6515,7 +7072,7 @@ } } }, - { + "createManagedIdentityForDeploymentScript": { "condition": "[not(empty(parameters('resourceProviders')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -6969,10 +7526,10 @@ } }, "dependsOn": [ - "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Resources/deployments', variables('deploymentNames').createResourceGroupForDeploymentScript)]" + "createResourceGroupForDeploymentScript" ] }, - { + "createRoleAssignmentsDeploymentScript": { "condition": "[not(empty(parameters('resourceProviders')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -6987,12 +7544,15 @@ "location": { "value": "[parameters('deploymentScriptLocation')]" }, - "principalId": "[if(not(empty(parameters('resourceProviders'))), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDeploymentScriptManagedIdentity), '2022-09-01').outputs.principalId.value), createObject('value', ''))]", + "principalId": "[if(not(empty(parameters('resourceProviders'))), createObject('value', reference('createManagedIdentityForDeploymentScript').outputs.principalId.value), createObject('value', ''))]", "roleDefinitionIdOrName": { "value": "Contributor" }, "subscriptionId": { "value": "[parameters('subscriptionId')]" + }, + "principalType": { + "value": "ServicePrincipal" } }, "template": { @@ -7001,8 +7561,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4635601566143603046" + "version": "0.28.1.47646", + "templateHash": "4097241605548087035" }, "name": "Role Assignments (All scopes)", "description": "This module deploys a Role Assignment at a Management Group, Subscription or Resource Group scope.", @@ -7107,8 +7667,8 @@ { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -7161,8 +7721,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "13749459126745145624" + "version": "0.28.1.47646", + "templateHash": "8906093264527258150" }, "name": "Role Assignments (Management Group scope)", "description": "This module deploys a Role Assignment at a Management Group scope.", @@ -7325,8 +7885,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4516670639800961845" + "version": "0.28.1.47646", + "templateHash": "707244099707019442" }, "name": "Role Assignments (Subscription scope)", "description": "This module deploys a Role Assignment at a Subscription scope.", @@ -7497,8 +8057,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "7241874480439813582" + "version": "0.28.1.47646", + "templateHash": "14591941439222880522" }, "name": "Role Assignments (Resource Group scope)", "description": "This module deploys a Role Assignment at a Resource Group scope.", @@ -7663,10 +8223,10 @@ } }, "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDeploymentScriptManagedIdentity)]" + "createManagedIdentityForDeploymentScript" ] }, - { + "createRoleAssignmentsDeploymentScriptStorageAccount": { "condition": "[not(empty(parameters('resourceProviders')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -7681,7 +8241,7 @@ "location": { "value": "[parameters('deploymentScriptLocation')]" }, - "principalId": "[if(not(empty(parameters('resourceProviders'))), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDeploymentScriptManagedIdentity), '2022-09-01').outputs.principalId.value), createObject('value', ''))]", + "principalId": "[if(not(empty(parameters('resourceProviders'))), createObject('value', reference('createManagedIdentityForDeploymentScript').outputs.principalId.value), createObject('value', ''))]", "roleDefinitionIdOrName": { "value": "/providers/Microsoft.Authorization/roleDefinitions/69566ab7-960f-475b-8e7c-b3118f30c6bd" }, @@ -7690,6 +8250,9 @@ }, "resourceGroupName": { "value": "[parameters('deploymentScriptResourceGroupName')]" + }, + "principalType": { + "value": "ServicePrincipal" } }, "template": { @@ -7698,8 +8261,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4635601566143603046" + "version": "0.28.1.47646", + "templateHash": "4097241605548087035" }, "name": "Role Assignments (All scopes)", "description": "This module deploys a Role Assignment at a Management Group, Subscription or Resource Group scope.", @@ -7804,8 +8367,8 @@ { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.ptn.authorization-roleassignment.{0}.{1}', replace('0.1.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -7858,8 +8421,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "13749459126745145624" + "version": "0.28.1.47646", + "templateHash": "8906093264527258150" }, "name": "Role Assignments (Management Group scope)", "description": "This module deploys a Role Assignment at a Management Group scope.", @@ -8022,8 +8585,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "4516670639800961845" + "version": "0.28.1.47646", + "templateHash": "707244099707019442" }, "name": "Role Assignments (Subscription scope)", "description": "This module deploys a Role Assignment at a Subscription scope.", @@ -8194,8 +8757,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "7241874480439813582" + "version": "0.28.1.47646", + "templateHash": "14591941439222880522" }, "name": "Role Assignments (Resource Group scope)", "description": "This module deploys a Role Assignment at a Resource Group scope.", @@ -8360,10 +8923,10 @@ } }, "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDeploymentScriptManagedIdentity)]" + "createManagedIdentityForDeploymentScript" ] }, - { + "createDsNsg": { "condition": "[not(empty(parameters('resourceProviders')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -8977,10 +9540,10 @@ } }, "dependsOn": [ - "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Resources/deployments', variables('deploymentNames').createResourceGroupForDeploymentScript)]" + "createResourceGroupForDeploymentScript" ] }, - { + "createDsStorageAccount": { "condition": "[not(empty(parameters('resourceProviders')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -9012,7 +9575,7 @@ "virtualNetworkRules": [ { "action": "Allow", - "id": "[if(not(empty(parameters('resourceProviders'))), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createdsVnet), '2022-09-01').outputs.subnetResourceIds.value[0], null())]" + "id": "[if(not(empty(parameters('resourceProviders'))), reference('createDsVnet').outputs.subnetResourceIds.value[0], null())]" } ] } @@ -13657,11 +14220,11 @@ } }, "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createdsVnet)]", - "[extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', take(format('{0}', variables('deploymentNames').createRoleAssignmentsDeploymentScriptStorageAccount), 64))]" + "createDsVnet", + "createRoleAssignmentsDeploymentScriptStorageAccount" ] }, - { + "createDsVnet": { "condition": "[not(empty(parameters('resourceProviders')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -13685,7 +14248,7 @@ "[parameters('virtualNetworkDeploymentScriptAddressPrefix')]" ] }, - "subnets": "[if(not(empty(parameters('resourceProviders'))), createObject('value', createArray(createObject('addressPrefix', if(not(empty(parameters('resourceProviders'))), cidrSubnet(parameters('virtualNetworkDeploymentScriptAddressPrefix'), 24, 0), null()), 'name', 'ds-subnet-001', 'networkSecurityGroupResourceId', if(not(empty(parameters('resourceProviders'))), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDsNsg), '2022-09-01').outputs.resourceId.value, null()), 'serviceEndpoints', createArray('Microsoft.Storage'), 'delegation', 'Microsoft.ContainerInstance/containerGroups'))), createObject('value', null()))]", + "subnets": "[if(not(empty(parameters('resourceProviders'))), createObject('value', createArray(createObject('addressPrefix', if(not(empty(parameters('resourceProviders'))), cidrSubnet(parameters('virtualNetworkDeploymentScriptAddressPrefix'), 24, 0), null()), 'name', 'ds-subnet-001', 'networkSecurityGroupResourceId', if(not(empty(parameters('resourceProviders'))), reference('createDsNsg').outputs.resourceId.value, null()), 'serviceEndpoints', createArray('Microsoft.Storage'), 'delegation', 'Microsoft.ContainerInstance/containerGroups'))), createObject('value', null()))]", "enableTelemetry": { "value": "[parameters('enableTelemetry')]" } @@ -13697,232 +14260,14 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15949466154563447171" + "version": "0.30.23.60470", + "templateHash": "12023193036665775110" }, "name": "Virtual Networks", "description": "This module deploys a Virtual Network (vNet).", "owner": "Azure/module-maintainers" }, "definitions": { - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } - } - } - }, - "nullable": true - }, "peeringType": { "type": "object", "properties": { @@ -14020,143 +14365,374 @@ "type": "bool", "nullable": true, "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." + "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." + } + } + } + }, + "subnetType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The Name of the subnet resource." + } + }, + "addressPrefix": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty." + } + }, + "addressPrefixes": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty." + } + }, + "applicationGatewayIPConfigurations": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application gateway IP configurations of virtual network resource." + } + }, + "delegation": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The delegation to enable on the subnet." + } + }, + "natGatewayResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the NAT Gateway to use for the subnet." + } + }, + "networkSecurityGroupResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the network security group to assign to the subnet." + } + }, + "privateEndpointNetworkPolicies": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled", + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. enable or disable apply network policies on private endpoint in the subnet." + } + }, + "privateLinkServiceNetworkPolicies": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. enable or disable apply network policies on private link service in the subnet." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "routeTableResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the route table to assign to the subnet." + } + }, + "serviceEndpointPolicies": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. An array of service endpoint policies." + } + }, + "serviceEndpoints": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The service endpoints to enable on the subnet." + } + }, + "defaultOutboundAccess": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Set this property to false to disable default outbound connectivity for all VMs in the subnet. This property can only be set at the time of subnet creation and cannot be updated for an existing subnet." + } + }, + "sharingScope": { + "type": "string", + "allowedValues": [ + "DelegatedServices", + "Tenant" + ], + "nullable": true, + "metadata": { + "description": "Optional. Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty." + } + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." } - } - } - }, - "subnetType": { - "type": "object", - "properties": { - "name": { + }, + "logAnalyticsDestinationType": { "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, "metadata": { - "description": "Required. The Name of the subnet resource." + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." } }, - "addressPrefix": { + "workspaceResourceId": { "type": "string", "nullable": true, "metadata": { - "description": "Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty." + "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." } }, - "addressPrefixes": { - "type": "array", - "items": { - "type": "string" - }, + "storageAccountResourceId": { + "type": "string", "nullable": true, "metadata": { - "description": "Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty." + "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." } }, - "applicationGatewayIPConfigurations": { - "type": "array", - "items": { - "type": "object" - }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Application gateway IP configurations of virtual network resource." + "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." } }, - "delegation": { + "eventHubName": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The delegation to enable on the subnet." + "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." } }, - "natGatewayResourceId": { + "marketplacePartnerResourceId": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The resource ID of the NAT Gateway to use for the subnet." + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } - }, - "networkSecurityGroupResourceId": { + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The resource ID of the network security group to assign to the subnet." + "description": "Optional. Specify the name of lock." } }, - "privateEndpointNetworkPolicies": { + "kind": { "type": "string", "allowedValues": [ - "", - "Disabled", - "Enabled" + "CanNotDelete", + "None", + "ReadOnly" ], "nullable": true, "metadata": { - "description": "Optional. enable or disable apply network policies on private endpoint in the subnet." + "description": "Optional. Specify the type of lock." } - }, - "privateLinkServiceNetworkPolicies": { + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { "type": "string", - "allowedValues": [ - "", - "Disabled", - "Enabled" - ], "nullable": true, "metadata": { - "description": "Optional. enable or disable apply network policies on private link service in the subnet." + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "roleDefinitionIdOrName": { + "type": "string", "metadata": { - "description": "Optional. Array of role assignments to create." + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, - "routeTableResourceId": { + "principalId": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. The resource ID of the route table to assign to the subnet." + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." } }, - "serviceEndpointPolicies": { - "type": "array", - "items": { - "type": "object" - }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], "nullable": true, "metadata": { - "description": "Optional. An array of service endpoint policies." + "description": "Optional. The principal type of the assigned principal ID." } }, - "serviceEndpoints": { - "type": "array", - "items": { - "type": "string" - }, + "description": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. The service endpoints to enable on the subnet." + "description": "Optional. The description of the role assignment." } }, - "defaultOutboundAccess": { - "type": "bool", + "condition": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Set this property to false to disable default outbound connectivity for all VMs in the subnet. This property can only be set at the time of subnet creation and cannot be updated for an existing subnet." + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." } }, - "sharingScope": { + "conditionVersion": { "type": "string", "allowedValues": [ - "DelegatedServices", - "Tenant" + "2.0" ], "nullable": true, "metadata": { - "description": "Optional. Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty." + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } } } }, @@ -14251,19 +14827,28 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -14312,7 +14897,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.network-virtualnetwork.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-virtualnetwork.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -14496,8 +15081,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5699372618313647761" + "version": "0.30.23.60470", + "templateHash": "6411714881793832751" }, "name": "Virtual Network Subnets", "description": "This module deploys a Virtual Network Subnet.", @@ -14505,77 +15090,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } } }, "parameters": { @@ -14638,11 +15225,12 @@ }, "privateEndpointNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", "Enabled", - "" + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private endpoint in the subnet." @@ -14650,11 +15238,10 @@ }, "privateLinkServiceNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", - "Enabled", - "" + "Enabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private link service in the subnet." @@ -14703,7 +15290,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -14753,8 +15344,8 @@ "routeTable": "[if(not(empty(parameters('routeTableResourceId'))), createObject('id', parameters('routeTableResourceId')), null())]", "natGateway": "[if(not(empty(parameters('natGatewayResourceId'))), createObject('id', parameters('natGatewayResourceId')), null())]", "delegations": "[if(not(empty(parameters('delegation'))), createArray(createObject('name', parameters('delegation'), 'properties', createObject('serviceName', parameters('delegation')))), createArray())]", - "privateEndpointNetworkPolicies": "[if(not(empty(parameters('privateEndpointNetworkPolicies'))), parameters('privateEndpointNetworkPolicies'), null())]", - "privateLinkServiceNetworkPolicies": "[if(not(empty(parameters('privateLinkServiceNetworkPolicies'))), parameters('privateLinkServiceNetworkPolicies'), null())]", + "privateEndpointNetworkPolicies": "[parameters('privateEndpointNetworkPolicies')]", + "privateLinkServiceNetworkPolicies": "[parameters('privateLinkServiceNetworkPolicies')]", "applicationGatewayIPConfigurations": "[parameters('applicationGatewayIPConfigurations')]", "serviceEndpointPolicies": "[parameters('serviceEndpointPolicies')]", "defaultOutboundAccess": "[parameters('defaultOutboundAccess')]", @@ -14875,8 +15466,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5206620163504251868" + "version": "0.30.23.60470", + "templateHash": "345394220621166229" }, "name": "Virtual Network Peerings", "description": "This module deploys a Virtual Network Peering.", @@ -14981,7 +15572,8 @@ } }, "dependsOn": [ - "virtualNetwork" + "virtualNetwork", + "virtualNetwork_subnets" ] }, "virtualNetwork_peering_remote": { @@ -15032,8 +15624,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5206620163504251868" + "version": "0.30.23.60470", + "templateHash": "345394220621166229" }, "name": "Virtual Network Peerings", "description": "This module deploys a Virtual Network Peering.", @@ -15138,7 +15730,8 @@ } }, "dependsOn": [ - "virtualNetwork" + "virtualNetwork", + "virtualNetwork_subnets" ] } }, @@ -15195,10 +15788,10 @@ } }, "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDsNsg)]" + "createDsNsg" ] }, - { + "registerResourceProviders": { "condition": "[not(empty(parameters('resourceProviders')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -15238,9 +15831,9 @@ "runOnce": { "value": true }, - "managedIdentities": "[if(not(empty(parameters('resourceProviders'))), createObject('value', createObject('userAssignedResourcesIds', createArray(reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDeploymentScriptManagedIdentity), '2022-09-01').outputs.resourceId.value))), createObject('value', null()))]", - "storageAccountResourceId": "[if(not(empty(parameters('resourceProviders'))), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDsStorageAccount), '2022-09-01').outputs.resourceId.value), createObject('value', null()))]", - "subnetResourceIds": "[if(not(empty(parameters('resourceProviders'))), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createdsVnet), '2022-09-01').outputs.subnetResourceIds.value), createObject('value', null()))]", + "managedIdentities": "[if(not(empty(parameters('resourceProviders'))), createObject('value', createObject('userAssignedResourcesIds', createArray(reference('createManagedIdentityForDeploymentScript').outputs.resourceId.value))), createObject('value', null()))]", + "storageAccountResourceId": "[if(not(empty(parameters('resourceProviders'))), createObject('value', reference('createDsStorageAccount').outputs.resourceId.value), createObject('value', null()))]", + "subnetResourceIds": "[if(not(empty(parameters('resourceProviders'))), createObject('value', reference('createDsVnet').outputs.subnetResourceIds.value), createObject('value', null()))]", "arguments": { "value": "[format('-resourceProviders ''{0}'' -resourceProvidersFeatures -subscriptionId {1}', variables('resourceProvidersFormatted'), parameters('subscriptionId'))]" }, @@ -15745,71 +16338,71 @@ } }, "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDsStorageAccount)]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createdsVnet)]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').createDeploymentScriptManagedIdentity)]" + "createDsStorageAccount", + "createDsVnet", + "createManagedIdentityForDeploymentScript" ] } - ], + }, "outputs": { "failedProviders": { "type": "string", - "value": "[if(not(empty(parameters('resourceProviders'))), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').registerResourceProviders), '2022-09-01').outputs.outputs.value.failedProvidersRegistrations, '')]" + "value": "[if(not(empty(parameters('resourceProviders'))), reference('registerResourceProviders').outputs.outputs.value.failedProvidersRegistrations, '')]" }, "failedFeatures": { "type": "string", - "value": "[if(not(empty(parameters('resourceProviders'))), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('deploymentScriptResourceGroupName')), 'Microsoft.Resources/deployments', variables('deploymentNames').registerResourceProviders), '2022-09-01').outputs.outputs.value.failedFeaturesRegistrations, '')]" + "value": "[if(not(empty(parameters('resourceProviders'))), reference('registerResourceProviders').outputs.outputs.value.failedFeaturesRegistrations, '')]" } } } }, "dependsOn": [ - "[extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', variables('deploymentNames').createSubscription)]" + "createSubscription" ] } - ], + }, "outputs": { "subscriptionId": { "type": "string", "metadata": { "description": "The Subscription ID that has been created or provided." }, - "value": "[if(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), reference(extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', variables('deploymentNames').createSubscription), '2022-09-01').outputs.subscriptionId.value, if(contains(variables('existingSubscriptionIDEmptyCheck'), 'No Subscription ID Provided'), variables('existingSubscriptionIDEmptyCheck'), format('{0}', parameters('existingSubscriptionId'))))]" + "value": "[if(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), reference('createSubscription').outputs.subscriptionId.value, if(contains(variables('existingSubscriptionIDEmptyCheck'), 'No Subscription ID Provided'), variables('existingSubscriptionIDEmptyCheck'), format('{0}', parameters('existingSubscriptionId'))))]" }, "subscriptionResourceId": { "type": "string", "metadata": { "description": "The Subscription Resource ID that has been created or provided." }, - "value": "[if(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), reference(extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', variables('deploymentNames').createSubscription), '2022-09-01').outputs.subscriptionResourceId.value, if(contains(variables('existingSubscriptionIDEmptyCheck'), 'No Subscription ID Provided'), variables('existingSubscriptionIDEmptyCheck'), format('/subscriptions/{0}', parameters('existingSubscriptionId'))))]" + "value": "[if(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), reference('createSubscription').outputs.subscriptionResourceId.value, if(contains(variables('existingSubscriptionIDEmptyCheck'), 'No Subscription ID Provided'), variables('existingSubscriptionIDEmptyCheck'), format('/subscriptions/{0}', parameters('existingSubscriptionId'))))]" }, "subscriptionAcceptOwnershipState": { "type": "string", "metadata": { "description": "The Subscription Owner State. Only used when creating MCA Subscriptions across tenants." }, - "value": "[if(and(and(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), not(empty(parameters('subscriptionTenantId')))), not(empty(parameters('subscriptionOwnerId')))), reference(extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', variables('deploymentNames').createSubscription), '2022-09-01').outputs.subscriptionAcceptOwnershipState.value, 'N/A')]" + "value": "[if(and(and(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), not(empty(parameters('subscriptionTenantId')))), not(empty(parameters('subscriptionOwnerId')))), reference('createSubscription').outputs.subscriptionAcceptOwnershipState.value, 'N/A')]" }, "subscriptionAcceptOwnershipUrl": { "type": "string", "metadata": { "description": "The Subscription Ownership URL. Only used when creating MCA Subscriptions across tenants." }, - "value": "[if(and(and(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), not(empty(parameters('subscriptionTenantId')))), not(empty(parameters('subscriptionOwnerId')))), reference(extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', variables('deploymentNames').createSubscription), '2022-09-01').outputs.subscriptionAcceptOwnershipUrl.value, 'N/A')]" + "value": "[if(and(and(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), not(empty(parameters('subscriptionTenantId')))), not(empty(parameters('subscriptionOwnerId')))), reference('createSubscription').outputs.subscriptionAcceptOwnershipUrl.value, 'N/A')]" }, "failedResourceProviders": { "type": "string", "metadata": { "description": "The resource providers that failed to register." }, - "value": "[if(not(empty(parameters('resourceProviders'))), reference(extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', variables('deploymentNames').createSubscriptionResources), '2022-09-01').outputs.failedProviders.value, '')]" + "value": "[if(not(empty(parameters('resourceProviders'))), reference('createSubscriptionResources').outputs.failedProviders.value, '')]" }, "failedResourceProvidersFeatures": { "type": "string", "metadata": { "description": "The resource providers features that failed to register." }, - "value": "[if(not(empty(parameters('resourceProviders'))), reference(extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', variables('deploymentNames').createSubscriptionResources), '2022-09-01').outputs.failedFeatures.value, '')]" + "value": "[if(not(empty(parameters('resourceProviders'))), reference('createSubscriptionResources').outputs.failedFeatures.value, '')]" } } } \ No newline at end of file diff --git a/avm/ptn/lz/sub-vending/modules/subResourceWrapper.bicep b/avm/ptn/lz/sub-vending/modules/subResourceWrapper.bicep index d0b80795eb..068205a588 100644 --- a/avm/ptn/lz/sub-vending/modules/subResourceWrapper.bicep +++ b/avm/ptn/lz/sub-vending/modules/subResourceWrapper.bicep @@ -86,7 +86,7 @@ param vHubRoutingIntentEnabled bool = false param roleAssignmentEnabled bool = false @sys.description('Supply an array of objects containing the details of the role assignments to create.') -param roleAssignments array = [] +param roleAssignments roleAssignmentType = [] @sys.description('Disable telemetry collection by this module. For more information on the telemetry collected by this module, that is controlled by this parameter, see this page in the wiki: [Telemetry Tracking Using Customer Usage Attribution (PID)](https://github.com/Azure/bicep-lz-vending/wiki/Telemetry)') param enableTelemetry bool = true @@ -178,7 +178,6 @@ param resourceProviders object = { 'Microsoft.Sql': [] 'Microsoft.Storage': [] 'Microsoft.StreamAnalytics': [] - 'Microsoft.TimeSeriesInsights': [] 'Microsoft.Web': [] } @@ -388,7 +387,7 @@ module tagResourceGroup 'tags.bicep' = if (virtualNetworkEnabled && !empty(virtu } } -module createLzVnet 'br/public:avm/res/network/virtual-network:0.4.0' = if (virtualNetworkEnabled && !empty(virtualNetworkName) && !empty(virtualNetworkAddressSpace) && !empty(virtualNetworkLocation) && !empty(virtualNetworkResourceGroupName)) { +module createLzVnet 'br/public:avm/res/network/virtual-network:0.5.0' = if (virtualNetworkEnabled && !empty(virtualNetworkName) && !empty(virtualNetworkAddressSpace) && !empty(virtualNetworkLocation) && !empty(virtualNetworkResourceGroupName)) { dependsOn: [ createResourceGroupForLzNetworking ] @@ -447,7 +446,7 @@ module createLzVirtualWanConnection 'hubVirtualNetworkConnections.bicep' = if (v } } -module createLzRoleAssignmentsSub 'br/public:avm/ptn/authorization/role-assignment:0.1.0' = [ +module createLzRoleAssignmentsSub 'br/public:avm/ptn/authorization/role-assignment:0.1.1' = [ for assignment in roleAssignmentsSubscription: if (roleAssignmentEnabled && !empty(roleAssignmentsSubscription)) { name: take( '${deploymentNames.createLzRoleAssignmentsSub}-${uniqueString(assignment.principalId, assignment.definition, assignment.relativeScope)}', @@ -458,11 +457,27 @@ module createLzRoleAssignmentsSub 'br/public:avm/ptn/authorization/role-assignme principalId: assignment.principalId roleDefinitionIdOrName: assignment.definition subscriptionId: subscriptionId + conditionVersion: !(empty(assignment.?roleAssignmentCondition ?? {})) + ? (assignment.?roleAssignmentCondition.?conditionVersion ?? '2.0') + : null + condition: (empty(assignment.?roleAssignmentCondition ?? {})) + ? null + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'constrainRoles' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeRolesType(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'constrainRolesAndPrincipalTypes' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeRolesAndPrincipalsTypes(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'constrainRolesAndPrincipals' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeRolesAndPrincipals(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'excludeRoles' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeExcludeRoles(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : !(empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? assignment.?roleAssignmentCondition.?delegationCode + : null } } ] -module createLzRoleAssignmentsRsgsSelf 'br/public:avm/ptn/authorization/role-assignment:0.1.0' = [ +module createLzRoleAssignmentsRsgsSelf 'br/public:avm/ptn/authorization/role-assignment:0.1.1' = [ for assignment in roleAssignmentsResourceGroupSelf: if (roleAssignmentEnabled && !empty(roleAssignmentsResourceGroupSelf)) { dependsOn: [ createResourceGroupForLzNetworking @@ -477,11 +492,27 @@ module createLzRoleAssignmentsRsgsSelf 'br/public:avm/ptn/authorization/role-ass roleDefinitionIdOrName: assignment.definition subscriptionId: subscriptionId resourceGroupName: split(assignment.relativeScope, '/')[2] + conditionVersion: !(empty(assignment.?roleAssignmentCondition ?? {})) + ? (assignment.?roleAssignmentCondition.?conditionVersion ?? '2.0') + : null + condition: (empty(assignment.?roleAssignmentCondition ?? {})) + ? null + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'constrainRoles' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeRolesType(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'constrainRolesAndPrincipalTypes' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeRolesAndPrincipalsTypes(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'constrainRolesAndPrincipals' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeRolesAndPrincipals(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'excludeRoles' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeExcludeRoles(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : !(empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? assignment.?roleAssignmentCondition.?delegationCode + : null } } ] -module createLzRoleAssignmentsRsgsNotSelf 'br/public:avm/ptn/authorization/role-assignment:0.1.0' = [ +module createLzRoleAssignmentsRsgsNotSelf 'br/public:avm/ptn/authorization/role-assignment:0.1.1' = [ for assignment in roleAssignmentsResourceGroupNotSelf: if (roleAssignmentEnabled && !empty(roleAssignmentsResourceGroupNotSelf)) { name: take( '${deploymentNames.createLzRoleAssignmentsRsgsNotSelf}-${uniqueString(assignment.principalId, assignment.definition, assignment.relativeScope)}', @@ -493,6 +524,22 @@ module createLzRoleAssignmentsRsgsNotSelf 'br/public:avm/ptn/authorization/role- roleDefinitionIdOrName: assignment.definition subscriptionId: subscriptionId resourceGroupName: split(assignment.relativeScope, '/')[2] + conditionVersion: !(empty(assignment.?roleAssignmentCondition ?? {})) + ? (assignment.?roleAssignmentCondition.?conditionVersion ?? '2.0') + : null + condition: (empty(assignment.?roleAssignmentCondition ?? {})) + ? null + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'constrainRoles' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeRolesType(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'constrainRolesAndPrincipalTypes' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeRolesAndPrincipalsTypes(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'constrainRolesAndPrincipals' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeRolesAndPrincipals(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : assignment.?roleAssignmentCondition.?roleConditionType.templateName == 'excludeRoles' && (empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? generateCodeExcludeRoles(any(assignment.?roleAssignmentCondition.?roleConditionType)) + : !(empty(assignment.?roleAssignmentCondition.?delegationCode)) + ? assignment.?roleAssignmentCondition.?delegationCode + : null } } ] @@ -520,17 +567,18 @@ module createManagedIdentityForDeploymentScript 'br/public:avm/res/managed-ident } } -module createRoleAssignmentsDeploymentScript 'br/public:avm/ptn/authorization/role-assignment:0.1.0' = if (!empty(resourceProviders)) { +module createRoleAssignmentsDeploymentScript 'br/public:avm/ptn/authorization/role-assignment:0.1.1' = if (!empty(resourceProviders)) { name: take('${deploymentNames.createRoleAssignmentsDeploymentScript}', 64) params: { location: deploymentScriptLocation principalId: !empty(resourceProviders) ? createManagedIdentityForDeploymentScript.outputs.principalId : '' roleDefinitionIdOrName: 'Contributor' subscriptionId: subscriptionId + principalType: 'ServicePrincipal' } } -module createRoleAssignmentsDeploymentScriptStorageAccount 'br/public:avm/ptn/authorization/role-assignment:0.1.0' = if (!empty(resourceProviders)) { +module createRoleAssignmentsDeploymentScriptStorageAccount 'br/public:avm/ptn/authorization/role-assignment:0.1.1' = if (!empty(resourceProviders)) { name: take('${deploymentNames.createRoleAssignmentsDeploymentScriptStorageAccount}', 64) params: { location: deploymentScriptLocation @@ -538,6 +586,7 @@ module createRoleAssignmentsDeploymentScriptStorageAccount 'br/public:avm/ptn/au roleDefinitionIdOrName: '/providers/Microsoft.Authorization/roleDefinitions/69566ab7-960f-475b-8e7c-b3118f30c6bd' subscriptionId: subscriptionId resourceGroupName: deploymentScriptResourceGroupName + principalType: 'ServicePrincipal' } } @@ -579,7 +628,7 @@ module createDsStorageAccount 'br/public:avm/res/storage/storage-account:0.9.1' } } -module createDsVnet 'br/public:avm/res/network/virtual-network:0.4.0' = if (!empty(resourceProviders)) { +module createDsVnet 'br/public:avm/res/network/virtual-network:0.5.0' = if (!empty(resourceProviders)) { scope: resourceGroup(subscriptionId, deploymentScriptResourceGroupName) name: deploymentNames.createdsVnet params: { @@ -641,3 +690,120 @@ output failedProviders string = !empty(resourceProviders) output failedFeatures string = !empty(resourceProviders) ? registerResourceProviders.outputs.outputs.failedFeaturesRegistrations : '' + +// ================ // +// Definitions // +// ================ // + +@export() +type roleAssignmentType = { + @description('Required. The principal ID of the user, group, or service principal.') + principalId: string + + @description('Required. The role definition ID or name.') + definition: string + + @description('Required. The relative scope of the role assignment.') + relativeScope: string + + @description('Optional. The condition for the role assignment.') + roleAssignmentCondition: roleAssignmentConditionType? +}[] + +// "Constrain Roles" - Condition template +@export() +type constrainRolesType = { + @description('Required. Name of the RBAC condition template.') + templateName: 'constrainRoles' + + @description('Required. The list of roles that are allowed to be assigned by the delegate.') + rolesToAssign: array +} + +// "Constrain Roles and Principal types" - Condition template +@export() +type constrainRolesAndPrincipalTypesType = { + @description('Required. Name of the RBAC condition template.') + templateName: 'constrainRolesAndPrincipalTypes' + + @description('Required. The list of roles that are allowed to be assigned by the delegate.') + rolesToAssign: array + + @description('Required. The list of principle types that are allowed to be assigned roles by the delegate.') + principleTypesToAssign: ('User' | 'Group' | 'ServicePrincipal')[] +} + +// "Constrain Roles and Principals" - Condition template +@export() +type constrainRolesAndPrincipalsType = { + @description('Required. Name of the RBAC condition template.') + templateName: 'constrainRolesAndPrincipals' + + @description('Required. The list of roles that are allowed to be assigned by the delegate.') + rolesToAssign: array + + @description('Required. The list of principals that are allowed to be assigned roles by the delegate.') + principalsToAssignTo: array +} + +// "Exclude Roles" - Condition template +@export() +type excludeRolesType = { + @description('Required. Name of the RBAC condition template.') + templateName: 'excludeRoles' + + @description('Required. The list of roles that are not allowed to be assigned by the delegate.') + ExludededRoles: array +} + +// Discriminator for the constrainedDelegationTemplatesType +@export() +@discriminator('templateName') +type constrainedDelegationTemplatesType = + | excludeRolesType + | constrainRolesType + | constrainRolesAndPrincipalTypesType + | constrainRolesAndPrincipalsType + +// Role Assignment Condition type +@export() +type roleAssignmentConditionType = { + @description('Optional. The type of template for the role assignment condition.') + roleConditionType: constrainedDelegationTemplatesType? + + @description('Optional. The version of the condition template.') + conditionVersion: '2.0'? + + @description('Optional. The code for a custom condition if no template is used. The user should supply their own custom code if the available templates are not matching their requirements. If a value is provided, this will overwrite any added template. All single quotes needs to be skipped using \'.') + delegationCode: string? +} + +// Functions to generate conditions' code + +@description('Generates the code for the "Constrain Roles" condition template.') +@export() +func generateCodeRolesType(constrainRoles constrainRolesType) string => + '((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/write\'})) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${joinArray(constrainRoles.rolesToAssign)}}) AND ((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/delete\'}) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${joinArray(constrainRoles.rolesToAssign)}}))))' + +@description('Generates the code for the "Constrain Roles and Principal types" condition template.') +@export() +func generateCodeRolesAndPrincipalsTypes(constrainRolesAndPrincipalsTypes constrainRolesAndPrincipalTypesType) string => + '((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/write\'}) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${joinArray(constrainRolesAndPrincipalsTypes.rolesToAssign)}} AND @Request[Microsoft.Authorization/roleAssignments:PrincipalType] ForAnyOfAnyValues:StringEqualsIgnoreCase {${joinArrayIgnoreCase(constrainRolesAndPrincipalsTypes.principleTypesToAssign)}})) AND ((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/delete\'})) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${joinArray(constrainRolesAndPrincipalsTypes.rolesToAssign)}} AND @Resource[Microsoft.Authorization/roleAssignments:PrincipalType] ForAnyOfAnyValues:StringEqualsIgnoreCase {${joinArrayIgnoreCase(constrainRolesAndPrincipalsTypes.principleTypesToAssign)}})))' + +@description('Generates the code for the "Constrain Roles and Principals" condition template.') +@export() +func generateCodeRolesAndPrincipals(constrainRolesAndPrincipals constrainRolesAndPrincipalsType) string => + '((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/write\'}) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${joinArray(constrainRolesAndPrincipals.rolesToAssign)}} AND @Request[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {${joinArray(constrainRolesAndPrincipals.principalsToAssignTo)}})) AND ((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/delete\'})) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${joinArray(constrainRolesAndPrincipals.rolesToAssign)}} AND @Resource[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {${joinArray(constrainRolesAndPrincipals.principalsToAssignTo)}})))' + +@description('Generates the code for the "Exclude Roles" condition template.') +@export() +func generateCodeExcludeRoles(excludeRoles excludeRolesType) string => + '((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/write\'}) OR ( @Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAllValues:GuidNotEquals {${joinArray(excludeRoles.ExludededRoles)}})) AND ((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/delete\'}) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAllValues:GuidNotEquals {${joinArray(excludeRoles.ExludededRoles)}}))))' + +// Helper functions +@export() +func joinArray(roles array) string => replace(join(roles, ','), '"', '') + +@export() +func joinArrayIgnoreCase(principalTypes array) string => + '\'${replace(replace(join(principalTypes, ','),'"','\''),',','\',\'')}\'' diff --git a/avm/ptn/lz/sub-vending/tests/e2e/defaults/main.test.bicep b/avm/ptn/lz/sub-vending/tests/e2e/defaults/main.test.bicep index 4917c76384..2a0aba1b3b 100644 --- a/avm/ptn/lz/sub-vending/tests/e2e/defaults/main.test.bicep +++ b/avm/ptn/lz/sub-vending/tests/e2e/defaults/main.test.bicep @@ -17,7 +17,7 @@ param namePrefix string = '#_namePrefix_#' param serviceShort string = 'ssamin' @description('Optional. A short guid for the subscription name.') -param subscriptionGuid string = toLower(substring(newGuid(), 0, 3)) +param subscriptionGuid string = toLower(substring(newGuid(), 0, 4)) module testDeployment '../../../main.bicep' = { name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${subscriptionGuid}' diff --git a/avm/ptn/lz/sub-vending/tests/e2e/hub-spoke/main.test.bicep b/avm/ptn/lz/sub-vending/tests/e2e/hub-spoke/main.test.bicep index 30d9130c61..e9a70825bb 100644 --- a/avm/ptn/lz/sub-vending/tests/e2e/hub-spoke/main.test.bicep +++ b/avm/ptn/lz/sub-vending/tests/e2e/hub-spoke/main.test.bicep @@ -17,7 +17,7 @@ param namePrefix string = '#_namePrefix_#' param serviceShort string = 'ssahs' @description('Optional. A short guid for the subscription name.') -param subscriptionGuid string = toLower(substring(newGuid(), 0, 3)) +param subscriptionGuid string = toLower(substring(newGuid(), 0, 4)) @description('Optional. The subscription id of the existing hub virtual network.') param vnetHubSubId string = '9948cae8-8c7c-4f5f-81c1-c53317cab23d' diff --git a/avm/ptn/lz/sub-vending/tests/e2e/rbac-condition/main.test.bicep b/avm/ptn/lz/sub-vending/tests/e2e/rbac-condition/main.test.bicep new file mode 100644 index 0000000000..c69578e2c9 --- /dev/null +++ b/avm/ptn/lz/sub-vending/tests/e2e/rbac-condition/main.test.bicep @@ -0,0 +1,63 @@ +metadata name = 'Using RBAC conditions.' +metadata description = 'This instance deploys the module with RBAC conditions for the role assignments.' + +targetScope = 'managementGroup' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +// This parameter needs to be updated with the billing account and the enrollment account of your enviornment. +@description('Optional. The subscription billing scope.') +param subscriptionBillingScope string = 'providers/Microsoft.Billing/billingAccounts/7690848/enrollmentAccounts/350580' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'ssarb' + +@description('Optional. A short guid for the subscription name.') +param subscriptionGuid string = toLower(substring(newGuid(), 0, 4)) + +module testDeployment '../../../main.bicep' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${subscriptionGuid}' + params: { + subscriptionAliasEnabled: true + subscriptionBillingScope: subscriptionBillingScope + subscriptionAliasName: 'dep-sub-blzv-tests-${namePrefix}-${serviceShort}-${subscriptionGuid}' + subscriptionDisplayName: 'dep-sub-blzv-tests-${namePrefix}-${serviceShort}-${subscriptionGuid}' + subscriptionTags: { + namePrefix: namePrefix + serviceShort: serviceShort + } + subscriptionWorkload: 'Production' + subscriptionManagementGroupAssociationEnabled: true + subscriptionManagementGroupId: 'bicep-lz-vending-automation-child' + resourceProviders: {} + roleAssignmentEnabled: true + roleAssignments: [ + { + principalId: '896b1162-be44-4b28-888a-d01acc1b4271' + definition: '/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168' + relativeScope: '' + roleAssignmentCondition: { + roleConditionType: { + principleTypesToAssign: [ + 'Group' + 'ServicePrincipal' + ] + rolesToAssign: [ + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ] + templateName: 'constrainRolesAndPrincipalTypes' + } + } + } + ] + } +} + +output createdSubId string = testDeployment.outputs.subscriptionId +output namePrefix string = namePrefix +output serviceShort string = serviceShort +output resourceLocation string = resourceLocation diff --git a/avm/ptn/lz/sub-vending/tests/e2e/rbac-condition/pester/main.tests.ps1 b/avm/ptn/lz/sub-vending/tests/e2e/rbac-condition/pester/main.tests.ps1 new file mode 100644 index 0000000000..e9fec1930e --- /dev/null +++ b/avm/ptn/lz/sub-vending/tests/e2e/rbac-condition/pester/main.tests.ps1 @@ -0,0 +1,64 @@ +param ( + [Parameter(Mandatory = $false)] + [hashtable] $TestInputData = @{} +) + +Describe 'Bicep Landing Zone (Sub) Vending Tests' { + + BeforeAll { + $subscriptionId = $TestInputData.DeploymentOutputs.createdSubId.Value + $namePrefix = $TestInputData.DeploymentOutputs.namePrefix.Value + $serviceShort = $TestInputData.DeploymentOutputs.serviceShort.Value + $location = $TestInputData.DeploymentOutputs.resourceLocation.Value + Update-AzConfig -DisplayBreakingChangeWarning $false + Select-AzSubscription -subscriptionId $subscriptionId + } + + Context 'Subscription Tests' { + BeforeAll { + $sub = Get-AzSubscription -SubscriptionId $subscriptionId -ErrorAction SilentlyContinue + } + + It 'Should have a Subscription with the correct name' { + $sub.Name | Should -BeLike "dep-sub-blzv-tests-$namePrefix-$serviceShort*" + } + + It 'Should have a Subscription that is enabled' { + $sub.State | Should -Be 'Enabled' + } + + It "Should have a Subscription with a tag key of 'namePrefix' with a value of '$namePrefix'" { + $sub.Tags.namePrefix | Should -Be $namePrefix + } + + It "Should have a Subscription with a tag key of 'serviceShort' with a value of '$serviceShort'" { + $sub.Tags.serviceShort | Should -Be $serviceShort + } + + It "Should have a Subscription that is a child of the Management Group with the ID of 'bicep-lz-vending-automation-child'" { + $mgAssociation = Get-AzManagementGroupSubscription -SubscriptionId $subscriptionId -GroupId 'bicep-lz-vending-automation-child' -ErrorAction SilentlyContinue + $mgAssociation.Id | Should -Be "/providers/Microsoft.Management/managementGroups/bicep-lz-vending-automation-child/subscriptions/$subscriptionId" + } + } + + Context 'Role-Based Access Control Assignment Tests' { + It 'Should Have a Role Assignment for an known AAD Group with the Role based access control administrator role directly upon the Subscription' { + $iterationCount = 0 + do { + $roleAssignment = Get-AzRoleAssignment -Scope "/subscriptions/$subscriptionId" -RoleDefinitionName 'Role Based Access Control Administrator' -ObjectId '896b1162-be44-4b28-888a-d01acc1b4271' -ErrorAction SilentlyContinue + if ($null -eq $roleAssignment) { + Write-Host "Waiting for Resource Group Role Assignments to be eventually consistent... Iteration: $($iterationCount)" -ForegroundColor Yellow + Start-Sleep -Seconds 40 + $iterationCount++ + } + } until ( + $roleAssignment -ne $null -or $iterationCount -ge 10 + ) + + $roleAssignment.ObjectId | Should -Be '896b1162-be44-4b28-888a-d01acc1b4271' + $roleAssignment.RoleDefinitionName | Should -Be 'Role Based Access Control Administrator' + $roleAssignment.scope | Should -Be "/subscriptions/$subscriptionId" + $roleAssignment.Condition | Should -Not -BeNullOrEmpty + } + } +} diff --git a/avm/ptn/lz/sub-vending/tests/e2e/vwan-spoke/main.test.bicep b/avm/ptn/lz/sub-vending/tests/e2e/vwan-spoke/main.test.bicep index d1ca22a289..f4ebc8730c 100644 --- a/avm/ptn/lz/sub-vending/tests/e2e/vwan-spoke/main.test.bicep +++ b/avm/ptn/lz/sub-vending/tests/e2e/vwan-spoke/main.test.bicep @@ -17,7 +17,7 @@ param namePrefix string = '#_namePrefix_#' param serviceShort string = 'ssawan' @description('Optional. A short guid for the subscription name.') -param subscriptionGuid string = toLower(substring(newGuid(), 0, 3)) +param subscriptionGuid string = toLower(substring(newGuid(), 0, 4)) @description('Optional. The subscription id of the hub virtual network.') param vwanHubSubId string = '9948cae8-8c7c-4f5f-81c1-c53317cab23d' diff --git a/avm/ptn/lz/sub-vending/version.json b/avm/ptn/lz/sub-vending/version.json index 8def869ede..daf1a794d9 100644 --- a/avm/ptn/lz/sub-vending/version.json +++ b/avm/ptn/lz/sub-vending/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.2", "pathFilters": [ "./main.json" ] diff --git a/avm/ptn/network/hub-networking/README.md b/avm/ptn/network/hub-networking/README.md index 490e420691..e702471bb4 100644 --- a/avm/ptn/network/hub-networking/README.md +++ b/avm/ptn/network/hub-networking/README.md @@ -18,15 +18,15 @@ This module is designed to simplify the creation of multi-region hub networks in | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | -| `Microsoft.Network/azureFirewalls` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/azureFirewalls) | +| `Microsoft.Network/azureFirewalls` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/azureFirewalls) | | `Microsoft.Network/bastionHosts` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2022-11-01/bastionHosts) | | `Microsoft.Network/publicIPAddresses` | [2023-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-09-01/publicIPAddresses) | | `Microsoft.Network/routeTables` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/routeTables) | -| `Microsoft.Network/routeTables/routes` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/routeTables/routes) | -| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks) | -| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/subnets) | +| `Microsoft.Network/routeTables/routes` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/routeTables/routes) | +| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks) | +| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/subnets) | | `Microsoft.Network/virtualNetworks/subnets` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/virtualNetworks/subnets) | -| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/virtualNetworkPeerings) | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/virtualNetworkPeerings) | ## Usage examples @@ -2203,10 +2203,10 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/azure-firewall:0.5.0` | Remote reference | +| `br/public:avm/res/network/azure-firewall:0.5.1` | Remote reference | | `br/public:avm/res/network/bastion-host:0.4.0` | Remote reference | | `br/public:avm/res/network/route-table:0.4.0` | Remote reference | -| `br/public:avm/res/network/virtual-network:0.4.0` | Remote reference | +| `br/public:avm/res/network/virtual-network:0.5.0` | Remote reference | ## Data Collection diff --git a/avm/ptn/network/hub-networking/main.bicep b/avm/ptn/network/hub-networking/main.bicep index 2f222c6bc0..15bb3053dc 100644 --- a/avm/ptn/network/hub-networking/main.bicep +++ b/avm/ptn/network/hub-networking/main.bicep @@ -43,7 +43,7 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableT } // Create hub virtual networks -module hubVirtualNetwork 'br/public:avm/res/network/virtual-network:0.4.0' = [ +module hubVirtualNetwork 'br/public:avm/res/network/virtual-network:0.5.0' = [ for (hub, index) in items(hubVirtualNetworks ?? {}): { name: '${uniqueString(deployment().name, location)}-${hub.key}-nvn' params: { @@ -166,7 +166,7 @@ module hubBastion 'br/public:avm/res/network/bastion-host:0.4.0' = [ // Create Azure Firewall if enabled // AzureFirewallSubnet is required to deploy Azure Firewall service. This subnet must exist in the subnets array if you enable Azure Firewall. -module hubAzureFirewall 'br/public:avm/res/network/azure-firewall:0.5.0' = [ +module hubAzureFirewall 'br/public:avm/res/network/azure-firewall:0.5.1' = [ for (hub, index) in items(hubVirtualNetworks ?? {}): if (hub.value.enableAzureFirewall) { name: '${uniqueString(deployment().name, location)}-${hub.key}-naf' params: { diff --git a/avm/ptn/network/hub-networking/main.json b/avm/ptn/network/hub-networking/main.json index 6cac966757..ac4ef0eb44 100644 --- a/avm/ptn/network/hub-networking/main.json +++ b/avm/ptn/network/hub-networking/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.3.12046", - "templateHash": "8969613921663763778" + "templateHash": "15226702818499942359" }, "name": "Hub Networking", "description": "This module is designed to simplify the creation of multi-region hub networks in Azure. It will create a number of virtual networks and subnets, and optionally peer them together in a mesh topology with routing.", @@ -793,232 +793,14 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15949466154563447171" + "version": "0.30.23.60470", + "templateHash": "12023193036665775110" }, "name": "Virtual Networks", "description": "This module deploys a Virtual Network (vNet).", "owner": "Azure/module-maintainers" }, "definitions": { - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } - } - } - }, - "nullable": true - }, "peeringType": { "type": "object", "properties": { @@ -1127,131 +909,362 @@ "name": { "type": "string", "metadata": { - "description": "Required. The Name of the subnet resource." + "description": "Required. The Name of the subnet resource." + } + }, + "addressPrefix": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty." + } + }, + "addressPrefixes": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty." + } + }, + "applicationGatewayIPConfigurations": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application gateway IP configurations of virtual network resource." + } + }, + "delegation": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The delegation to enable on the subnet." + } + }, + "natGatewayResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the NAT Gateway to use for the subnet." + } + }, + "networkSecurityGroupResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the network security group to assign to the subnet." + } + }, + "privateEndpointNetworkPolicies": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled", + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. enable or disable apply network policies on private endpoint in the subnet." + } + }, + "privateLinkServiceNetworkPolicies": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. enable or disable apply network policies on private link service in the subnet." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "routeTableResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the route table to assign to the subnet." + } + }, + "serviceEndpointPolicies": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. An array of service endpoint policies." + } + }, + "serviceEndpoints": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The service endpoints to enable on the subnet." + } + }, + "defaultOutboundAccess": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Set this property to false to disable default outbound connectivity for all VMs in the subnet. This property can only be set at the time of subnet creation and cannot be updated for an existing subnet." + } + }, + "sharingScope": { + "type": "string", + "allowedValues": [ + "DelegatedServices", + "Tenant" + ], + "nullable": true, + "metadata": { + "description": "Optional. Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty." + } + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." } }, - "addressPrefix": { + "logAnalyticsDestinationType": { "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], "nullable": true, "metadata": { - "description": "Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty." + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." } }, - "addressPrefixes": { - "type": "array", - "items": { - "type": "string" - }, + "workspaceResourceId": { + "type": "string", "nullable": true, "metadata": { - "description": "Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty." + "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." } }, - "applicationGatewayIPConfigurations": { - "type": "array", - "items": { - "type": "object" - }, + "storageAccountResourceId": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Application gateway IP configurations of virtual network resource." + "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." } }, - "delegation": { + "eventHubAuthorizationRuleResourceId": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The delegation to enable on the subnet." + "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." } }, - "natGatewayResourceId": { + "eventHubName": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The resource ID of the NAT Gateway to use for the subnet." + "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." } }, - "networkSecurityGroupResourceId": { + "marketplacePartnerResourceId": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The resource ID of the network security group to assign to the subnet." + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } - }, - "privateEndpointNetworkPolicies": { + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { "type": "string", - "allowedValues": [ - "", - "Disabled", - "Enabled" - ], "nullable": true, "metadata": { - "description": "Optional. enable or disable apply network policies on private endpoint in the subnet." + "description": "Optional. Specify the name of lock." } }, - "privateLinkServiceNetworkPolicies": { + "kind": { "type": "string", "allowedValues": [ - "", - "Disabled", - "Enabled" + "CanNotDelete", + "None", + "ReadOnly" ], "nullable": true, "metadata": { - "description": "Optional. enable or disable apply network policies on private link service in the subnet." + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "roleDefinitionIdOrName": { + "type": "string", "metadata": { - "description": "Optional. Array of role assignments to create." + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, - "routeTableResourceId": { + "principalId": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. The resource ID of the route table to assign to the subnet." + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." } }, - "serviceEndpointPolicies": { - "type": "array", - "items": { - "type": "object" - }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], "nullable": true, "metadata": { - "description": "Optional. An array of service endpoint policies." + "description": "Optional. The principal type of the assigned principal ID." } }, - "serviceEndpoints": { - "type": "array", - "items": { - "type": "string" - }, + "description": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. The service endpoints to enable on the subnet." + "description": "Optional. The description of the role assignment." } }, - "defaultOutboundAccess": { - "type": "bool", + "condition": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Set this property to false to disable default outbound connectivity for all VMs in the subnet. This property can only be set at the time of subnet creation and cannot be updated for an existing subnet." + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." } }, - "sharingScope": { + "conditionVersion": { "type": "string", "allowedValues": [ - "DelegatedServices", - "Tenant" + "2.0" ], "nullable": true, "metadata": { - "description": "Optional. Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty." + "description": "Optional. Version of the condition." } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" } } } @@ -1347,19 +1360,28 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -1408,7 +1430,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.network-virtualnetwork.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-virtualnetwork.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1592,8 +1614,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5699372618313647761" + "version": "0.30.23.60470", + "templateHash": "6411714881793832751" }, "name": "Virtual Network Subnets", "description": "This module deploys a Virtual Network Subnet.", @@ -1601,77 +1623,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.1.0" + } + } } }, "parameters": { @@ -1734,11 +1758,12 @@ }, "privateEndpointNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", "Enabled", - "" + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private endpoint in the subnet." @@ -1746,11 +1771,10 @@ }, "privateLinkServiceNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", - "Enabled", - "" + "Enabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private link service in the subnet." @@ -1799,7 +1823,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -1849,8 +1877,8 @@ "routeTable": "[if(not(empty(parameters('routeTableResourceId'))), createObject('id', parameters('routeTableResourceId')), null())]", "natGateway": "[if(not(empty(parameters('natGatewayResourceId'))), createObject('id', parameters('natGatewayResourceId')), null())]", "delegations": "[if(not(empty(parameters('delegation'))), createArray(createObject('name', parameters('delegation'), 'properties', createObject('serviceName', parameters('delegation')))), createArray())]", - "privateEndpointNetworkPolicies": "[if(not(empty(parameters('privateEndpointNetworkPolicies'))), parameters('privateEndpointNetworkPolicies'), null())]", - "privateLinkServiceNetworkPolicies": "[if(not(empty(parameters('privateLinkServiceNetworkPolicies'))), parameters('privateLinkServiceNetworkPolicies'), null())]", + "privateEndpointNetworkPolicies": "[parameters('privateEndpointNetworkPolicies')]", + "privateLinkServiceNetworkPolicies": "[parameters('privateLinkServiceNetworkPolicies')]", "applicationGatewayIPConfigurations": "[parameters('applicationGatewayIPConfigurations')]", "serviceEndpointPolicies": "[parameters('serviceEndpointPolicies')]", "defaultOutboundAccess": "[parameters('defaultOutboundAccess')]", @@ -1971,8 +1999,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5206620163504251868" + "version": "0.30.23.60470", + "templateHash": "345394220621166229" }, "name": "Virtual Network Peerings", "description": "This module deploys a Virtual Network Peering.", @@ -2077,7 +2105,8 @@ } }, "dependsOn": [ - "virtualNetwork" + "virtualNetwork", + "virtualNetwork_subnets" ] }, "virtualNetwork_peering_remote": { @@ -2128,8 +2157,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5206620163504251868" + "version": "0.30.23.60470", + "templateHash": "345394220621166229" }, "name": "Virtual Network Peerings", "description": "This module deploys a Virtual Network Peering.", @@ -2234,7 +2263,8 @@ } }, "dependsOn": [ - "virtualNetwork" + "virtualNetwork", + "virtualNetwork_subnets" ] } }, @@ -4059,8 +4089,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15791050653269307918" + "version": "0.30.23.60470", + "templateHash": "7234474154283943675" }, "name": "Azure Firewalls", "description": "This module deploys an Azure Firewall.", @@ -4845,6 +4875,13 @@ "description": "Optional. Zone numbers e.g. 1,2,3." } }, + "enableForcedTunneling": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enable/Disable forced tunneling." + } + }, "diagnosticSettings": { "$ref": "#/definitions/diagnosticSettingType", "metadata": { @@ -4904,7 +4941,7 @@ } ], "azureSkuName": "[if(empty(parameters('virtualNetworkResourceId')), 'AZFW_Hub', 'AZFW_VNet')]", - "requiresManagementIp": "[if(equals(parameters('azureSkuTier'), 'Basic'), true(), false())]", + "requiresManagementIp": "[if(or(equals(parameters('azureSkuTier'), 'Basic'), parameters('enableForcedTunneling')), true(), false())]", "isCreateDefaultManagementIP": "[and(empty(parameters('managementIPResourceID')), variables('requiresManagementIp'))]", "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", @@ -4919,7 +4956,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.network-azurefirewall.{0}.{1}', replace('0.5.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-azurefirewall.{0}.{1}', replace('0.5.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -4937,7 +4974,7 @@ }, "azureFirewall": { "type": "Microsoft.Network/azureFirewalls", - "apiVersion": "2023-04-01", + "apiVersion": "2024-01-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "zones": "[if(equals(length(parameters('zones')), 0), null(), parameters('zones'))]", @@ -5071,7 +5108,7 @@ "_generator": { "name": "bicep", "version": "0.29.47.4906", - "templateHash": "14450344965065009842" + "templateHash": "16693645977675862540" }, "name": "Public IP Addresses", "description": "This module deploys a Public IP Address.", @@ -5520,7 +5557,7 @@ "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" } }, "resources": { @@ -5528,7 +5565,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.5.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.6.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -5724,7 +5761,7 @@ "_generator": { "name": "bicep", "version": "0.29.47.4906", - "templateHash": "14450344965065009842" + "templateHash": "16693645977675862540" }, "name": "Public IP Addresses", "description": "This module deploys a Public IP Address.", @@ -6173,7 +6210,7 @@ "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" } }, "resources": { @@ -6181,7 +6218,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.5.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.6.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -6399,7 +6436,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('azureFirewall', '2023-04-01', 'full').location]" + "value": "[reference('azureFirewall', '2024-01-01', 'full').location]" } } } diff --git a/avm/ptn/network/private-link-private-dns-zones/README.md b/avm/ptn/network/private-link-private-dns-zones/README.md index e5f3e732ba..8686381c3f 100644 --- a/avm/ptn/network/private-link-private-dns-zones/README.md +++ b/avm/ptn/network/private-link-private-dns-zones/README.md @@ -103,10 +103,19 @@ module privateLinkPrivateDnsZones 'br/public:avm/ptn/network/private-link-privat name: 'privateLinkPrivateDnsZonesDeployment' params: { location: '' + lock: { + kind: 'CanNotDelete' + name: 'pdnsZonesLock' + } privateLinkPrivateDnsZones: [ 'testpdnszone1.int' 'testpdnszone2.local' ] + tags: { + Environment: 'Example' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } virtualNetworkResourceIdsToLinkTo: [ '' ] @@ -129,12 +138,25 @@ module privateLinkPrivateDnsZones 'br/public:avm/ptn/network/private-link-privat "location": { "value": "" }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "pdnsZonesLock" + } + }, "privateLinkPrivateDnsZones": { "value": [ "testpdnszone1.int", "testpdnszone2.local" ] }, + "tags": { + "value": { + "Environment": "Example", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, "virtualNetworkResourceIdsToLinkTo": { "value": [ "" @@ -155,10 +177,19 @@ module privateLinkPrivateDnsZones 'br/public:avm/ptn/network/private-link-privat using 'br/public:avm/ptn/network/private-link-private-dns-zones:' param location = '' +param lock = { + kind: 'CanNotDelete' + name: 'pdnsZonesLock' +} param privateLinkPrivateDnsZones = [ 'testpdnszone1.int' 'testpdnszone2.local' ] +param tags = { + Environment: 'Example' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' +} param virtualNetworkResourceIdsToLinkTo = [ '' ] @@ -234,7 +265,9 @@ param virtualNetworkResourceIdsToLinkTo = [ | :-- | :-- | :-- | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`location`](#parameter-location) | string | Azure region where the each of the Private Link Private DNS Zones created will be deployed, default to Resource Group location if not specified. | +| [`lock`](#parameter-lock) | object | The lock settings for the Private Link Private DNS Zones created. | | [`privateLinkPrivateDnsZones`](#parameter-privatelinkprivatednszones) | array | An array of Private Link Private DNS Zones to create. Each item must be a valid DNS zone name.

    **NOTE:**

  • Private Link Private DNS Zones that have `{{regionCode}}` in the name will be replaced with the Geo Code of the Region you specified in the `location` parameter, if available, as documented [here](https://learn.microsoft.com/azure/private-link/private-endpoint-dns#:~:text=Note-,In%20the%20above%20text%2C%20%7BregionCode%7D%20refers%20to%20the%20region%20code%20(for%20example%2C%20eus%20for%20East%20US%20and%20ne%20for%20North%20Europe).%20Refer%20to%20the%20following%20lists%20for%20regions%20codes%3A,-All%20public%20clouds).

    - e.g. If `UK South` or `uksouth` was specified as the region in the `location` parameter, `{{regionCode}}` would be replaced with `uks` in the Private DNS Zone name.

  • Private Link Private DNS Zones that have `{{regionName}}` in the name will be replaced with the short name of the Region you specified in the `location` parameter, if available, as documented [here](https://learn.microsoft.com/azure/private-link/private-endpoint-dns).

    - e.g. If `UK South` or `uksouth` was specified as the region in the `location` parameter, `{{regionName}}` would be replaced with `uksouth` in the Private DNS Zone name.

    **IMPORTANT:**

    The folowing Private Link Private DNS Zones have been removed from the default value for this parameter as they require additional placeholders to be replaced that will only be known by the caller of the module at runtime and cannot be determined by the module itself. If you have a requirement to create these Private Link Private DNS Zones, you must provide the full list of Private Link Private DNS Zones to create as an array in the `privateLinkPrivateDnsZones` parameter, using the default value as a reference. The list of Private Link Private DNS Zones that have been removed are:

  • `{subzone}.privatelink.{regionName}.azmk8s.io`
  • `privatelink.{dnsPrefix}.database.windows.net`
  • `privatelink.{partitionId}.azurestaticapps.net`

    We have also removed the following Private Link Private DNS Zones from the default value for this parameter as they should only be created and used with in specific scenarios:

  • `privatelink.azure.com`.

    | +| [`tags`](#parameter-tags) | object | Tags of the Private Link Private DNS Zones created. | | [`virtualNetworkResourceIdsToLinkTo`](#parameter-virtualnetworkresourceidstolinkto) | array | An array of Virtual Network Resource IDs to link to the Private Link Private DNS Zones. Each item must be a valid Virtual Network Resource ID. | ### Parameter: `enableTelemetry` @@ -253,6 +286,42 @@ Azure region where the each of the Private Link Private DNS Zones created will b - Type: string - Default: `[resourceGroup().location]` +### Parameter: `lock` + +The lock settings for the Private Link Private DNS Zones created. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + ### Parameter: `privateLinkPrivateDnsZones` An array of Private Link Private DNS Zones to create. Each item must be a valid DNS zone name.

    **NOTE:**

  • Private Link Private DNS Zones that have `{{regionCode}}` in the name will be replaced with the Geo Code of the Region you specified in the `location` parameter, if available, as documented [here](https://learn.microsoft.com/azure/private-link/private-endpoint-dns#:~:text=Note-,In%20the%20above%20text%2C%20%7BregionCode%7D%20refers%20to%20the%20region%20code%20(for%20example%2C%20eus%20for%20East%20US%20and%20ne%20for%20North%20Europe).%20Refer%20to%20the%20following%20lists%20for%20regions%20codes%3A,-All%20public%20clouds).

    - e.g. If `UK South` or `uksouth` was specified as the region in the `location` parameter, `{{regionCode}}` would be replaced with `uks` in the Private DNS Zone name.

  • Private Link Private DNS Zones that have `{{regionName}}` in the name will be replaced with the short name of the Region you specified in the `location` parameter, if available, as documented [here](https://learn.microsoft.com/azure/private-link/private-endpoint-dns).

    - e.g. If `UK South` or `uksouth` was specified as the region in the `location` parameter, `{{regionName}}` would be replaced with `uksouth` in the Private DNS Zone name.

    **IMPORTANT:**

    The folowing Private Link Private DNS Zones have been removed from the default value for this parameter as they require additional placeholders to be replaced that will only be known by the caller of the module at runtime and cannot be determined by the module itself. If you have a requirement to create these Private Link Private DNS Zones, you must provide the full list of Private Link Private DNS Zones to create as an array in the `privateLinkPrivateDnsZones` parameter, using the default value as a reference. The list of Private Link Private DNS Zones that have been removed are:

  • `{subzone}.privatelink.{regionName}.azmk8s.io`
  • `privatelink.{dnsPrefix}.database.windows.net`
  • `privatelink.{partitionId}.azurestaticapps.net`

    We have also removed the following Private Link Private DNS Zones from the default value for this parameter as they should only be created and used with in specific scenarios:

  • `privatelink.azure.com`.

    @@ -262,11 +331,9 @@ An array of Private Link Private DNS Zones to create. Each item must be a valid - Default: ```Bicep [ - '{regionCode}.privatelink.backup.windowsazure.com' '{regionName}.data.privatelink.azurecr.io' - '{regionName}.privatelink.batch.azure.com' - '{regionName}.service.privatelink.batch.azure.com' 'privatelink-global.wvd.microsoft.com' + 'privatelink.{regionCode}.backup.windowsazure.com' 'privatelink.{regionName}.azmk8s.io' 'privatelink.{regionName}.kusto.windows.net' 'privatelink.adf.azure.com' @@ -288,6 +355,7 @@ An array of Private Link Private DNS Zones to create. Each item must be a valid 'privatelink.azureiotcentral.com' 'privatelink.azurestaticapps.net' 'privatelink.azurewebsites.net' + 'privatelink.batch.azure.com' 'privatelink.blob.core.windows.net' 'privatelink.cassandra.cosmos.azure.com' 'privatelink.cognitiveservices.azure.com' @@ -341,6 +409,13 @@ An array of Private Link Private DNS Zones to create. Each item must be a valid ] ``` +### Parameter: `tags` + +Tags of the Private Link Private DNS Zones created. + +- Required: No +- Type: object + ### Parameter: `virtualNetworkResourceIdsToLinkTo` An array of Virtual Network Resource IDs to link to the Private Link Private DNS Zones. Each item must be a valid Virtual Network Resource ID. @@ -363,7 +438,8 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/private-dns-zone:0.3.0` | Remote reference | +| `br/public:avm/res/network/private-dns-zone:0.6.0` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/ptn/network/private-link-private-dns-zones/main.bicep b/avm/ptn/network/private-link-private-dns-zones/main.bicep index 279ab04a17..7786799de6 100644 --- a/avm/ptn/network/private-link-private-dns-zones/main.bicep +++ b/avm/ptn/network/private-link-private-dns-zones/main.bicep @@ -5,6 +5,13 @@ metadata owner = 'jtracey93' @description('Optional. Azure region where the each of the Private Link Private DNS Zones created will be deployed, default to Resource Group location if not specified.') param location string = resourceGroup().location +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' +@description('Optional. The lock settings for the Private Link Private DNS Zones created.') +param lock lockType? + +@description('Optional. Tags of the Private Link Private DNS Zones created.') +param tags object? + @description(''' Optional. An array of Private Link Private DNS Zones to create. Each item must be a valid DNS zone name. @@ -56,8 +63,7 @@ param privateLinkPrivateDnsZones array = [ 'privatelink.pbidedicated.windows.net' 'privatelink.tip1.powerquery.microsoft.com' 'privatelink.azuredatabricks.net' - '{regionName}.privatelink.batch.azure.com' - '{regionName}.service.privatelink.batch.azure.com' + 'privatelink.batch.azure.com' 'privatelink-global.wvd.microsoft.com' 'privatelink.wvd.microsoft.com' 'privatelink.{regionName}.azmk8s.io' @@ -92,7 +98,7 @@ param privateLinkPrivateDnsZones array = [ 'privatelink.digitaltwins.azure.net' 'privatelink.media.azure.net' 'privatelink.azure-automation.net' - '{regionCode}.privatelink.backup.windowsazure.com' + 'privatelink.{regionCode}.backup.windowsazure.com' 'privatelink.siterecovery.windowsazure.com' 'privatelink.monitor.azure.com' 'privatelink.oms.opinsights.azure.com' @@ -287,7 +293,7 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableT } } -module pdnsZones 'br/public:avm/res/network/private-dns-zone:0.3.0' = [ +module pdnsZones 'br/public:avm/res/network/private-dns-zone:0.6.0' = [ for zone in combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink: { name: '${uniqueString(deployment().name, zone.pdnsZoneName, location)}-pdns-zone-deployment' params: { @@ -298,6 +304,9 @@ module pdnsZones 'br/public:avm/res/network/private-dns-zone:0.3.0' = [ virtualNetworkResourceId: vnet } ] + lock: lock + tags: tags + enableTelemetry: enableTelemetry } } ] diff --git a/avm/ptn/network/private-link-private-dns-zones/main.json b/avm/ptn/network/private-link-private-dns-zones/main.json index 76be09b3bd..e18a8049bf 100644 --- a/avm/ptn/network/private-link-private-dns-zones/main.json +++ b/avm/ptn/network/private-link-private-dns-zones/main.json @@ -1,16 +1,49 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "9730251377827517821" + "version": "0.30.23.60470", + "templateHash": "6071389975562170906" }, "name": "avm/ptn/network/private-link-private-dns-zones", "description": "Private Link Private DNS Zones", "owner": "jtracey93" }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + } + }, "parameters": { "location": { "type": "string", @@ -19,6 +52,20 @@ "description": "Optional. Azure region where the each of the Private Link Private DNS Zones created will be deployed, default to Resource Group location if not specified." } }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. The lock settings for the Private Link Private DNS Zones created." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Private Link Private DNS Zones created." + } + }, "privateLinkPrivateDnsZones": { "type": "array", "defaultValue": [ @@ -44,8 +91,7 @@ "privatelink.pbidedicated.windows.net", "privatelink.tip1.powerquery.microsoft.com", "privatelink.azuredatabricks.net", - "{regionName}.privatelink.batch.azure.com", - "{regionName}.service.privatelink.batch.azure.com", + "privatelink.batch.azure.com", "privatelink-global.wvd.microsoft.com", "privatelink.wvd.microsoft.com", "privatelink.{regionName}.azmk8s.io", @@ -79,7 +125,7 @@ "privatelink.digitaltwins.azure.net", "privatelink.media.azure.net", "privatelink.azure-automation.net", - "{regionCode}.privatelink.backup.windowsazure.com", + "privatelink.{regionCode}.backup.windowsazure.com", "privatelink.siterecovery.windowsazure.com", "privatelink.monitor.azure.com", "privatelink.oms.opinsights.azure.com", @@ -253,8 +299,8 @@ "locationLoweredAndSpacesRemoved": "[if(contains(variables('locationLowered'), ' '), variables('azureRegionShortNameDisplayNameAsKey')[variables('locationLowered')], variables('locationLowered'))]", "combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink": "[map(range(0, length(variables('privateLinkPrivateDnsZonesReplacedWithRegionName'))), lambda('i', createObject('pdnsZoneName', variables('privateLinkPrivateDnsZonesReplacedWithRegionName')[lambdaVariables('i')], 'virtualNetworkResourceIdsToLinkTo', parameters('virtualNetworkResourceIdsToLinkTo'))))]" }, - "resources": [ - { + "resources": { + "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", @@ -274,7 +320,7 @@ } } }, - { + "pdnsZones": { "copy": { "name": "pdnsZones", "count": "[length(variables('combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink'))]" @@ -299,6 +345,15 @@ "input": "[createObject('registrationEnabled', false(), 'virtualNetworkResourceId', variables('combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink')[copyIndex()].virtualNetworkResourceIdsToLinkTo[copyIndex('value')])]" } ] + }, + "lock": { + "value": "[parameters('lock')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" } }, "template": { @@ -308,8 +363,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "11412633288570781407" + "version": "0.29.47.4906", + "templateHash": "5518185016108244461" }, "name": "Private DNS Zones", "description": "This module deploys a Private DNS zone.", @@ -321,6 +376,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -887,6 +949,51 @@ } }, "nullable": true + }, + "virtualNetworkLinkType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 80, + "metadata": { + "description": "Optional. The resource name." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the virtual network to link." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Azure Region where the resource lives." + } + }, + "registrationEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + } + } + }, + "nullable": true } }, "parameters": { @@ -945,8 +1052,7 @@ } }, "virtualNetworkLinks": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/virtualNetworkLinkType", "metadata": { "description": "Optional. Array of custom objects describing vNet links of the DNS zone. Each object should contain properties 'virtualNetworkResourceId' 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." } @@ -986,21 +1092,28 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" } }, "resources": { "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privatednszone.{0}.{1}', replace('0.3.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privatednszone.{0}.{1}', replace('0.6.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1040,20 +1153,20 @@ "privateDnsZone_roleAssignments": { "copy": { "name": "privateDnsZone_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateDnsZones/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateDnsZones', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "privateDnsZone" @@ -1099,8 +1212,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "8657463061873174631" + "version": "0.29.47.4906", + "templateHash": "1641889417618452692" }, "name": "Private DNS Zone A record", "description": "This module deploys a Private DNS Zone A record.", @@ -1112,6 +1225,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -1216,13 +1336,20 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -1249,20 +1376,20 @@ "A_roleAssignments": { "copy": { "name": "A_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateDnsZones/{0}/A/{1}', parameters('privateDnsZoneName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "A" @@ -1338,8 +1465,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "1725749611610769138" + "version": "0.29.47.4906", + "templateHash": "17163414995652446126" }, "name": "Private DNS Zone AAAA record", "description": "This module deploys a Private DNS Zone AAAA record.", @@ -1351,6 +1478,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -1455,13 +1589,20 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -1488,20 +1629,20 @@ "AAAA_roleAssignments": { "copy": { "name": "AAAA_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateDnsZones/{0}/AAAA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "AAAA" @@ -1577,8 +1718,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "12750497126800708872" + "version": "0.29.47.4906", + "templateHash": "2493714129104385633" }, "name": "Private DNS Zone CNAME record", "description": "This module deploys a Private DNS Zone CNAME record.", @@ -1590,6 +1731,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -1694,13 +1842,20 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -1727,20 +1882,20 @@ "CNAME_roleAssignments": { "copy": { "name": "CNAME_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateDnsZones/{0}/CNAME/{1}', parameters('privateDnsZoneName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "CNAME" @@ -1816,8 +1971,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "13512848802819943036" + "version": "0.29.47.4906", + "templateHash": "10928449924272756679" }, "name": "Private DNS Zone MX record", "description": "This module deploys a Private DNS Zone MX record.", @@ -1829,6 +1984,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -1933,13 +2095,20 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -1966,20 +2135,20 @@ "MX_roleAssignments": { "copy": { "name": "MX_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateDnsZones/{0}/MX/{1}', parameters('privateDnsZoneName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "MX" @@ -2055,8 +2224,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "5069219418696231980" + "version": "0.29.47.4906", + "templateHash": "13191587152357386110" }, "name": "Private DNS Zone PTR record", "description": "This module deploys a Private DNS Zone PTR record.", @@ -2068,6 +2237,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -2172,13 +2348,20 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -2205,20 +2388,20 @@ "PTR_roleAssignments": { "copy": { "name": "PTR_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateDnsZones/{0}/PTR/{1}', parameters('privateDnsZoneName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "PTR" @@ -2294,8 +2477,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "8649693365938652763" + "version": "0.29.47.4906", + "templateHash": "12872700379964561295" }, "name": "Private DNS Zone SOA record", "description": "This module deploys a Private DNS Zone SOA record.", @@ -2307,6 +2490,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -2411,13 +2601,20 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -2444,20 +2641,20 @@ "SOA_roleAssignments": { "copy": { "name": "SOA_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SOA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "SOA" @@ -2533,8 +2730,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "1580431299497536987" + "version": "0.29.47.4906", + "templateHash": "12918383495773487180" }, "name": "Private DNS Zone SRV record", "description": "This module deploys a Private DNS Zone SRV record.", @@ -2546,6 +2743,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -2650,13 +2854,20 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -2683,20 +2894,20 @@ "SRV_roleAssignments": { "copy": { "name": "SRV_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SRV/{1}', parameters('privateDnsZoneName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "SRV" @@ -2772,8 +2983,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "1628766837655887758" + "version": "0.29.47.4906", + "templateHash": "128006490354221158" }, "name": "Private DNS Zone TXT record", "description": "This module deploys a Private DNS Zone TXT record.", @@ -2785,6 +2996,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -2889,13 +3107,20 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -2922,20 +3147,20 @@ "TXT_roleAssignments": { "copy": { "name": "TXT_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateDnsZones/{0}/TXT/{1}', parameters('privateDnsZoneName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "TXT" @@ -3011,8 +3236,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "8423159394395901832" + "version": "0.29.47.4906", + "templateHash": "1713449351614683457" }, "name": "Private DNS Zone Virtual Network Link", "description": "This module deploys a Private DNS Zone Virtual Network Link.", @@ -3154,7 +3379,7 @@ } } } - ], + }, "outputs": { "combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink": { "type": "array", diff --git a/avm/ptn/network/private-link-private-dns-zones/tests/e2e/max/main.test.bicep b/avm/ptn/network/private-link-private-dns-zones/tests/e2e/max/main.test.bicep index be5b4b820e..6ba237a4ac 100644 --- a/avm/ptn/network/private-link-private-dns-zones/tests/e2e/max/main.test.bicep +++ b/avm/ptn/network/private-link-private-dns-zones/tests/e2e/max/main.test.bicep @@ -58,6 +58,15 @@ module testDeployment '../../../main.bicep' = [ virtualNetworkResourceIdsToLinkTo: [ nestedDependencies.outputs.vnetResourceId ] + lock: { + kind: 'CanNotDelete' + name: 'pdnsZonesLock' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Example' + Role: 'DeploymentValidation' + } } } ] diff --git a/avm/ptn/network/private-link-private-dns-zones/version.json b/avm/ptn/network/private-link-private-dns-zones/version.json index 8def869ede..729ac87673 100644 --- a/avm/ptn/network/private-link-private-dns-zones/version.json +++ b/avm/ptn/network/private-link-private-dns-zones/version.json @@ -1,7 +1,7 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.2", "pathFilters": [ "./main.json" ] -} +} \ No newline at end of file diff --git a/avm/ptn/virtual-machine-images/azure-image-builder/README.md b/avm/ptn/virtual-machine-images/azure-image-builder/README.md index 0ddfb123e2..b7ca714ac2 100644 --- a/avm/ptn/virtual-machine-images/azure-image-builder/README.md +++ b/avm/ptn/virtual-machine-images/azure-image-builder/README.md @@ -26,9 +26,9 @@ This module provides you with a packaged solution to create custom images using | `Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities/federatedIdentityCredentials) | | `Microsoft.Network/privateEndpoints` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints) | | `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints/privateDnsZoneGroups) | -| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks) | -| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/subnets) | -| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/virtualNetworkPeerings) | +| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks) | +| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/subnets) | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/virtualNetworkPeerings) | | `Microsoft.Resources/deploymentScripts` | [2023-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Resources/2023-08-01/deploymentScripts) | | `Microsoft.Resources/resourceGroups` | [2024-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Resources/2024-03-01/resourceGroups) | | `Microsoft.Storage/storageAccounts` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Storage/2022-09-01/storageAccounts) | @@ -1180,6 +1180,11 @@ The files to upload to the Assets Storage Account. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-storageaccountfilestouploadname) | string | The name of the environment variable. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | | [`secureValue`](#parameter-storageaccountfilestouploadsecurevalue) | securestring | The value of the secure environment variable. | | [`value`](#parameter-storageaccountfilestouploadvalue) | string | The value of the environment variable. | diff --git a/avm/ptn/virtual-machine-images/azure-image-builder/main.bicep b/avm/ptn/virtual-machine-images/azure-image-builder/main.bicep index 34d5a6048e..997353e120 100644 --- a/avm/ptn/virtual-machine-images/azure-image-builder/main.bicep +++ b/avm/ptn/virtual-machine-images/azure-image-builder/main.bicep @@ -597,10 +597,10 @@ type storageAccountFilesToUploadType = { @description('Required. The name of the environment variable.') name: string - @description('Required. The value of the secure environment variable.') + @description('Optional. The value of the secure environment variable.') @secure() secureValue: string? - @description('Required. The value of the environment variable.') + @description('Optional. The value of the environment variable.') value: string? } diff --git a/avm/ptn/virtual-machine-images/azure-image-builder/main.json b/avm/ptn/virtual-machine-images/azure-image-builder/main.json index e8e8b71562..7173f704ee 100644 --- a/avm/ptn/virtual-machine-images/azure-image-builder/main.json +++ b/avm/ptn/virtual-machine-images/azure-image-builder/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "4580919221810730076" + "templateHash": "9111396630441610187" }, "name": "Custom Images using Azure Image Builder", "description": "This module provides you with a packaged solution to create custom images using the Azure Image Builder service publishing to an Azure Compute Gallery.", @@ -26,14 +26,14 @@ "type": "securestring", "nullable": true, "metadata": { - "description": "Required. The value of the secure environment variable." + "description": "Optional. The value of the secure environment variable." } }, "value": { "type": "string", "nullable": true, "metadata": { - "description": "Required. The value of the environment variable." + "description": "Optional. The value of the environment variable." } } }, diff --git a/avm/res/analysis-services/server/README.md b/avm/res/analysis-services/server/README.md index 746d2e0701..c6cbf5f1e7 100644 --- a/avm/res/analysis-services/server/README.md +++ b/avm/res/analysis-services/server/README.md @@ -13,6 +13,7 @@ This module deploys an Analysis Services Server. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types @@ -615,7 +616,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -725,7 +726,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -951,6 +952,14 @@ Tags of the resource. | `resourceGroupName` | string | The resource group the analysis service was deployed into. | | `resourceId` | string | The resource ID of the analysis service. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/analysis-services/server/main.bicep b/avm/res/analysis-services/server/main.bicep index a308a8afc3..f37233e165 100644 --- a/avm/res/analysis-services/server/main.bicep +++ b/avm/res/analysis-services/server/main.bicep @@ -26,14 +26,17 @@ param firewallSettings object = { @description('Optional. Location for all Resources.') param location string = resourceGroup().location +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the resource.') param tags object? @@ -165,85 +168,3 @@ output resourceGroupName string = resourceGroup().name @description('The location the resource was deployed into.') output location string = server.location - -// =============== // -// Definitions // -// =============== // - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? diff --git a/avm/res/analysis-services/server/main.json b/avm/res/analysis-services/server/main.json index 73e2047e7f..e43d0f41be 100644 --- a/avm/res/analysis-services/server/main.json +++ b/avm/res/analysis-services/server/main.json @@ -5,14 +5,136 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13383500180025970135" + "version": "0.30.23.60470", + "templateHash": "783447731005535223" }, "name": "Analysis Services Servers", "description": "This module deploys an Analysis Services Server.", "owner": "Azure/module-maintainers" }, "definitions": { + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, "lockType": { "type": "object", "properties": { @@ -36,200 +158,87 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -277,19 +286,28 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/api-management/service/README.md b/avm/res/api-management/service/README.md index 42c1636201..f53359c277 100644 --- a/avm/res/api-management/service/README.md +++ b/avm/res/api-management/service/README.md @@ -2431,7 +2431,7 @@ A list of availability zones denoting where the resource needs to come from. Onl ## Notes -The latest version of this module only includes supported versions of the API Management resource. All unsupported versions of API Management have been removed from the related parameters. See the [API Management stv1 platform retirement](!https://learn.microsoft.com/en-us/azure/api-management/breaking-changes/stv1-platform-retirement-august-2024) article for more details. +The latest version of this module only includes supported versions of the API Management resource. All unsupported versions of API Management have been removed from the related parameters. See the [API Management stv1 platform retirement](https://learn.microsoft.com/en-us/azure/api-management/breaking-changes/stv1-platform-retirement-august-2024) article for more details. ### Parameter Usage: `apiManagementServicePolicy` diff --git a/avm/res/api-management/service/api-version-set/main.json b/avm/res/api-management/service/api-version-set/main.json index 061641030c..5578690d60 100644 --- a/avm/res/api-management/service/api-version-set/main.json +++ b/avm/res/api-management/service/api-version-set/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2492486199367242598" + "version": "0.31.34.60546", + "templateHash": "4169716301128870956" }, "name": "API Management Service API Version Sets", "description": "This module deploys an API Management Service API Version Set.", diff --git a/avm/res/api-management/service/api/diagnostics/main.json b/avm/res/api-management/service/api/diagnostics/main.json index 6db7e0f400..f38a7d145b 100644 --- a/avm/res/api-management/service/api/diagnostics/main.json +++ b/avm/res/api-management/service/api/diagnostics/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2531959928497745895" + "version": "0.31.34.60546", + "templateHash": "5353729184860596208" }, "name": "API Management Service APIs Diagnostics.", "description": "This module deploys an API Management Service API Diagnostics.", diff --git a/avm/res/api-management/service/api/main.json b/avm/res/api-management/service/api/main.json index a87b3409db..32a0de7df8 100644 --- a/avm/res/api-management/service/api/main.json +++ b/avm/res/api-management/service/api/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "17036957862982683599" + "version": "0.31.34.60546", + "templateHash": "79502668979653596" }, "name": "API Management Service APIs", "description": "This module deploys an API Management Service API.", @@ -245,10 +245,7 @@ "type": "[parameters('type')]", "value": "[parameters('value')]", "wsdlSelector": "[coalesce(parameters('wsdlSelector'), createObject())]" - }, - "dependsOn": [ - "service" - ] + } }, "policy": { "copy": { @@ -283,8 +280,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "5643177447182050438" + "version": "0.31.34.60546", + "templateHash": "7084313641171504315" }, "name": "API Management Service APIs Policies", "description": "This module deploys an API Management Service API Policy.", @@ -430,8 +427,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2531959928497745895" + "version": "0.31.34.60546", + "templateHash": "5353729184860596208" }, "name": "API Management Service APIs Diagnostics.", "description": "This module deploys an API Management Service API Diagnostics.", diff --git a/avm/res/api-management/service/api/policy/main.json b/avm/res/api-management/service/api/policy/main.json index af5ae11307..f65064267e 100644 --- a/avm/res/api-management/service/api/policy/main.json +++ b/avm/res/api-management/service/api/policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "5643177447182050438" + "version": "0.31.34.60546", + "templateHash": "7084313641171504315" }, "name": "API Management Service APIs Policies", "description": "This module deploys an API Management Service API Policy.", diff --git a/avm/res/api-management/service/authorization-server/main.json b/avm/res/api-management/service/authorization-server/main.json index 50d0897a93..41509bb54c 100644 --- a/avm/res/api-management/service/authorization-server/main.json +++ b/avm/res/api-management/service/authorization-server/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "17927787726774417819" + "version": "0.31.34.60546", + "templateHash": "7143680740173420481" }, "name": "API Management Service Authorization Servers", "description": "This module deploys an API Management Service Authorization Server.", diff --git a/avm/res/api-management/service/backend/main.json b/avm/res/api-management/service/backend/main.json index c3ae5f49b2..f6757a8df6 100644 --- a/avm/res/api-management/service/backend/main.json +++ b/avm/res/api-management/service/backend/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14706757128951530017" + "version": "0.31.34.60546", + "templateHash": "8388368953433969607" }, "name": "API Management Service Backends", "description": "This module deploys an API Management Service Backend.", @@ -114,10 +114,7 @@ "tls": "[parameters('tls')]", "url": "[parameters('url')]", "protocol": "[parameters('protocol')]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { diff --git a/avm/res/api-management/service/cache/main.json b/avm/res/api-management/service/cache/main.json index 285f53b0fb..1e9937f722 100644 --- a/avm/res/api-management/service/cache/main.json +++ b/avm/res/api-management/service/cache/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2750555671183513052" + "version": "0.31.34.60546", + "templateHash": "11909687365337883274" }, "name": "API Management Service Caches", "description": "This module deploys an API Management Service Cache.", @@ -68,10 +68,7 @@ "connectionString": "[parameters('connectionString')]", "useFromLocation": "[parameters('useFromLocation')]", "resourceId": "[parameters('resourceId')]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { diff --git a/avm/res/api-management/service/identity-provider/main.json b/avm/res/api-management/service/identity-provider/main.json index 6768ba8a3e..293b1b230a 100644 --- a/avm/res/api-management/service/identity-provider/main.json +++ b/avm/res/api-management/service/identity-provider/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "1342690797398622979" + "version": "0.31.34.60546", + "templateHash": "11902978823059118045" }, "name": "API Management Service Identity Providers", "description": "This module deploys an API Management Service Identity Provider.", @@ -141,10 +141,7 @@ "clientId": "[parameters('clientId')]", "clientLibrary": "[parameters('clientLibrary')]", "clientSecret": "[parameters('clientSecret')]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { diff --git a/avm/res/api-management/service/loggers/README.md b/avm/res/api-management/service/logger/README.md similarity index 92% rename from avm/res/api-management/service/loggers/README.md rename to avm/res/api-management/service/logger/README.md index c0fabec510..769f788fe5 100644 --- a/avm/res/api-management/service/loggers/README.md +++ b/avm/res/api-management/service/logger/README.md @@ -20,8 +20,8 @@ This module deploys an API Management Service Logger. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`loggerType`](#parameter-loggertype) | string | Logger type. | | [`name`](#parameter-name) | string | Resource Name. | +| [`type`](#parameter-type) | string | Logger type. | **Conditional parameters** @@ -35,10 +35,17 @@ This module deploys an API Management Service Logger. | Parameter | Type | Description | | :-- | :-- | :-- | +| [`description`](#parameter-description) | string | Logger description. | | [`isBuffered`](#parameter-isbuffered) | bool | Whether records are buffered in the logger before publishing. | -| [`loggerDescription`](#parameter-loggerdescription) | string | Logger description. | -### Parameter: `loggerType` +### Parameter: `name` + +Resource Name. + +- Required: Yes +- Type: string + +### Parameter: `type` Logger type. @@ -53,13 +60,6 @@ Logger type. ] ``` -### Parameter: `name` - -Resource Name. - -- Required: Yes -- Type: string - ### Parameter: `apiManagementServiceName` The name of the parent API Management service. Required if the template is used in a standalone deployment. @@ -81,6 +81,14 @@ Required if loggerType = applicationInsights or azureEventHub. Azure Resource Id - Required: Yes - Type: string +### Parameter: `description` + +Logger description. + +- Required: No +- Type: string +- Default: `''` + ### Parameter: `isBuffered` Whether records are buffered in the logger before publishing. @@ -89,13 +97,6 @@ Whether records are buffered in the logger before publishing. - Type: bool - Default: `True` -### Parameter: `loggerDescription` - -Logger description. - -- Required: Yes -- Type: string - ## Outputs | Output | Type | Description | diff --git a/avm/res/api-management/service/logger/main.bicep b/avm/res/api-management/service/logger/main.bicep new file mode 100644 index 0000000000..0397eb4c99 --- /dev/null +++ b/avm/res/api-management/service/logger/main.bicep @@ -0,0 +1,55 @@ +metadata name = 'API Management Service Loggers' +metadata description = 'This module deploys an API Management Service Logger.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Conditional. The name of the parent API Management service. Required if the template is used in a standalone deployment.') +param apiManagementServiceName string + +@sys.description('Required. Resource Name.') +param name string + +@sys.description('Optional. Logger description.') +param description string = '' + +@sys.description('Optional. Whether records are buffered in the logger before publishing.') +param isBuffered bool = true + +@sys.description('Required. Logger type.') +@allowed([ + 'applicationInsights' + 'azureEventHub' + 'azureMonitor' +]) +param type string + +@sys.description('Conditional. Required if loggerType = applicationInsights or azureEventHub. Azure Resource Id of a log target (either Azure Event Hub resource or Azure Application Insights resource).') +param targetResourceId string + +@secure() +@sys.description('Conditional. Required if loggerType = applicationInsights or azureEventHub. The name and SendRule connection string of the event hub for azureEventHub logger. Instrumentation key for applicationInsights logger.') +param credentials object + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource loggers 'Microsoft.ApiManagement/service/loggers@2022-08-01' = { + name: name + parent: service + properties: { + credentials: credentials + description: description + isBuffered: isBuffered + loggerType: type + resourceId: targetResourceId + } +} + +@sys.description('The resource ID of the logger.') +output resourceId string = loggers.id + +@sys.description('The name of the logger.') +output name string = loggers.name + +@sys.description('The resource group the named value was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/api-management/service/loggers/main.json b/avm/res/api-management/service/logger/main.json similarity index 92% rename from avm/res/api-management/service/loggers/main.json rename to avm/res/api-management/service/logger/main.json index 7d3305a3cd..cce73b9b5c 100644 --- a/avm/res/api-management/service/loggers/main.json +++ b/avm/res/api-management/service/logger/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "12834599511984803283" + "version": "0.31.34.60546", + "templateHash": "11518344218995825129" }, "name": "API Management Service Loggers", "description": "This module deploys an API Management Service Logger.", @@ -24,8 +24,9 @@ "description": "Required. Resource Name." } }, - "loggerDescription": { + "description": { "type": "string", + "defaultValue": "", "metadata": { "description": "Optional. Logger description." } @@ -37,7 +38,7 @@ "description": "Optional. Whether records are buffered in the logger before publishing." } }, - "loggerType": { + "type": { "type": "string", "allowedValues": [ "applicationInsights", @@ -68,9 +69,9 @@ "name": "[format('{0}/{1}', parameters('apiManagementServiceName'), parameters('name'))]", "properties": { "credentials": "[parameters('credentials')]", - "description": "[parameters('loggerDescription')]", + "description": "[parameters('description')]", "isBuffered": "[parameters('isBuffered')]", - "loggerType": "[parameters('loggerType')]", + "loggerType": "[parameters('type')]", "resourceId": "[parameters('targetResourceId')]" } } diff --git a/avm/res/api-management/service/loggers/main.bicep b/avm/res/api-management/service/loggers/main.bicep deleted file mode 100644 index 6f7d1af8fb..0000000000 --- a/avm/res/api-management/service/loggers/main.bicep +++ /dev/null @@ -1,55 +0,0 @@ -metadata name = 'API Management Service Loggers' -metadata description = 'This module deploys an API Management Service Logger.' -metadata owner = 'Azure/module-maintainers' - -@description('Conditional. The name of the parent API Management service. Required if the template is used in a standalone deployment.') -param apiManagementServiceName string - -@description('Required. Resource Name.') -param name string - -@description('Optional. Logger description.') -param loggerDescription string - -@description('Optional. Whether records are buffered in the logger before publishing.') -param isBuffered bool = true - -@description('Required. Logger type.') -@allowed([ - 'applicationInsights' - 'azureEventHub' - 'azureMonitor' -]) -param loggerType string - -@description('Conditional. Required if loggerType = applicationInsights or azureEventHub. Azure Resource Id of a log target (either Azure Event Hub resource or Azure Application Insights resource).') -param targetResourceId string - -@secure() -@description('Conditional. Required if loggerType = applicationInsights or azureEventHub. The name and SendRule connection string of the event hub for azureEventHub logger. Instrumentation key for applicationInsights logger.') -param credentials object - -resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { - name: apiManagementServiceName -} - -resource loggers 'Microsoft.ApiManagement/service/loggers@2022-08-01' = { - name: name - parent: service - properties: { - credentials: credentials - description: loggerDescription - isBuffered: isBuffered - loggerType: loggerType - resourceId: targetResourceId - } -} - -@description('The resource ID of the logger.') -output resourceId string = loggers.id - -@description('The name of the logger.') -output name string = loggers.name - -@description('The resource group the named value was deployed into.') -output resourceGroupName string = resourceGroup().name diff --git a/avm/res/api-management/service/main.bicep b/avm/res/api-management/service/main.bicep index 37a49b86c0..cc18535d18 100644 --- a/avm/res/api-management/service/main.bicep +++ b/avm/res/api-management/service/main.bicep @@ -409,16 +409,16 @@ module service_identityProviders 'identity-provider/main.bicep' = [ } ] -module service_loggers 'loggers/main.bicep' = [ +module service_loggers 'logger/main.bicep' = [ for (logger, index) in loggers: { name: '${uniqueString(deployment().name, location)}-Apim-Logger-${index}' params: { name: logger.name apiManagementServiceName: service.name credentials: logger.?credentials ?? {} - isBuffered: logger.?isBuffered ?? true - loggerDescription: logger.?loggerDescription ?? '' - loggerType: logger.?loggerType ?? 'azureMonitor' + isBuffered: logger.?isBuffered + description: logger.?loggerDescription + type: logger.?loggerType ?? 'azureMonitor' targetResourceId: logger.?targetResourceId ?? '' } dependsOn: [ diff --git a/avm/res/api-management/service/main.json b/avm/res/api-management/service/main.json index fc42a71966..82b4b88203 100644 --- a/avm/res/api-management/service/main.json +++ b/avm/res/api-management/service/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "7676062632439815762" + "version": "0.31.34.60546", + "templateHash": "5338224658105001512" }, "name": "API Management Services", "description": "This module deploys an API Management Service. The default deployment is set to use a Premium SKU to align with Microsoft WAF-aligned best practices. In most cases, non-prod deployments should use a lower-tier SKU.", @@ -791,8 +791,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "17036957862982683599" + "version": "0.31.34.60546", + "templateHash": "79502668979653596" }, "name": "API Management Service APIs", "description": "This module deploys an API Management Service API.", @@ -1031,10 +1031,7 @@ "type": "[parameters('type')]", "value": "[parameters('value')]", "wsdlSelector": "[coalesce(parameters('wsdlSelector'), createObject())]" - }, - "dependsOn": [ - "service" - ] + } }, "policy": { "copy": { @@ -1069,8 +1066,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "5643177447182050438" + "version": "0.31.34.60546", + "templateHash": "7084313641171504315" }, "name": "API Management Service APIs Policies", "description": "This module deploys an API Management Service API Policy.", @@ -1216,8 +1213,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2531959928497745895" + "version": "0.31.34.60546", + "templateHash": "5353729184860596208" }, "name": "API Management Service APIs Diagnostics.", "description": "This module deploys an API Management Service API Diagnostics.", @@ -1444,8 +1441,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2492486199367242598" + "version": "0.31.34.60546", + "templateHash": "4169716301128870956" }, "name": "API Management Service API Version Sets", "description": "This module deploys an API Management Service API Version Set.", @@ -1585,8 +1582,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "17927787726774417819" + "version": "0.31.34.60546", + "templateHash": "7143680740173420481" }, "name": "API Management Service Authorization Servers", "description": "This module deploys an API Management Service Authorization Server.", @@ -1835,8 +1832,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14706757128951530017" + "version": "0.31.34.60546", + "templateHash": "8388368953433969607" }, "name": "API Management Service Backends", "description": "This module deploys an API Management Service Backend.", @@ -1944,10 +1941,7 @@ "tls": "[parameters('tls')]", "url": "[parameters('url')]", "protocol": "[parameters('protocol')]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { @@ -2019,8 +2013,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2750555671183513052" + "version": "0.31.34.60546", + "templateHash": "11909687365337883274" }, "name": "API Management Service Caches", "description": "This module deploys an API Management Service Cache.", @@ -2082,10 +2076,7 @@ "connectionString": "[parameters('connectionString')]", "useFromLocation": "[parameters('useFromLocation')]", "resourceId": "[parameters('resourceId')]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { @@ -2177,8 +2168,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2531959928497745895" + "version": "0.31.34.60546", + "templateHash": "5353729184860596208" }, "name": "API Management Service APIs Diagnostics.", "description": "This module deploys an API Management Service API Diagnostics.", @@ -2407,8 +2398,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "1342690797398622979" + "version": "0.31.34.60546", + "templateHash": "11902978823059118045" }, "name": "API Management Service Identity Providers", "description": "This module deploys an API Management Service Identity Provider.", @@ -2543,10 +2534,7 @@ "clientId": "[parameters('clientId')]", "clientLibrary": "[parameters('clientLibrary')]", "clientSecret": "[parameters('clientSecret')]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { @@ -2602,12 +2590,12 @@ "value": "[coalesce(tryGet(parameters('loggers')[copyIndex()], 'credentials'), createObject())]" }, "isBuffered": { - "value": "[coalesce(tryGet(parameters('loggers')[copyIndex()], 'isBuffered'), true())]" + "value": "[tryGet(parameters('loggers')[copyIndex()], 'isBuffered')]" }, - "loggerDescription": { - "value": "[coalesce(tryGet(parameters('loggers')[copyIndex()], 'loggerDescription'), '')]" + "description": { + "value": "[tryGet(parameters('loggers')[copyIndex()], 'loggerDescription')]" }, - "loggerType": { + "type": { "value": "[coalesce(tryGet(parameters('loggers')[copyIndex()], 'loggerType'), 'azureMonitor')]" }, "targetResourceId": { @@ -2620,8 +2608,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "12834599511984803283" + "version": "0.31.34.60546", + "templateHash": "11518344218995825129" }, "name": "API Management Service Loggers", "description": "This module deploys an API Management Service Logger.", @@ -2640,8 +2628,9 @@ "description": "Required. Resource Name." } }, - "loggerDescription": { + "description": { "type": "string", + "defaultValue": "", "metadata": { "description": "Optional. Logger description." } @@ -2653,7 +2642,7 @@ "description": "Optional. Whether records are buffered in the logger before publishing." } }, - "loggerType": { + "type": { "type": "string", "allowedValues": [ "applicationInsights", @@ -2684,9 +2673,9 @@ "name": "[format('{0}/{1}', parameters('apiManagementServiceName'), parameters('name'))]", "properties": { "credentials": "[parameters('credentials')]", - "description": "[parameters('loggerDescription')]", + "description": "[parameters('description')]", "isBuffered": "[parameters('isBuffered')]", - "loggerType": "[parameters('loggerType')]", + "loggerType": "[parameters('type')]", "resourceId": "[parameters('targetResourceId')]" } } @@ -2764,8 +2753,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "10162843567606353040" + "version": "0.31.34.60546", + "templateHash": "5493266151487858395" }, "name": "API Management Service Named Values", "description": "This module deploys an API Management Service Named Value.", @@ -2839,10 +2828,7 @@ "displayName": "[parameters('displayName')]", "value": "[if(variables('keyVaultEmpty'), parameters('value'), null())]", "keyVault": "[if(not(variables('keyVaultEmpty')), parameters('keyVault'), null())]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { @@ -2905,8 +2891,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14869704072680236257" + "version": "0.31.34.60546", + "templateHash": "9587521329160400551" }, "name": "API Management Service Portal Settings", "description": "This module deploys an API Management Service Portal Setting.", @@ -3004,8 +2990,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "9395795206748286282" + "version": "0.31.34.60546", + "templateHash": "957115286202001780" }, "name": "API Management Service Policies", "description": "This module deploys an API Management Service Policy.", @@ -3139,8 +3125,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "8029364311033748838" + "version": "0.31.34.60546", + "templateHash": "3551579457056086397" }, "name": "API Management Service Products", "description": "This module deploys an API Management Service Product.", @@ -3268,8 +3254,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "602104798329438871" + "version": "0.31.34.60546", + "templateHash": "11213919899113582129" }, "name": "API Management Service Products APIs", "description": "This module deploys an API Management Service Product API.", @@ -3358,8 +3344,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "5238408376918932137" + "version": "0.31.34.60546", + "templateHash": "10245602090275457578" }, "name": "API Management Service Products Groups", "description": "This module deploys an API Management Service Product Group.", @@ -3518,8 +3504,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "16082435269276611452" + "version": "0.31.34.60546", + "templateHash": "17857709197993310769" }, "name": "API Management Service Subscriptions", "description": "This module deploys an API Management Service Subscription.", @@ -3607,10 +3593,7 @@ "secondaryKey": "[parameters('secondaryKey')]", "state": "[parameters('state')]", "allowTracing": "[parameters('allowTracing')]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { diff --git a/avm/res/api-management/service/named-value/main.json b/avm/res/api-management/service/named-value/main.json index b182535671..7e25a3a988 100644 --- a/avm/res/api-management/service/named-value/main.json +++ b/avm/res/api-management/service/named-value/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "10162843567606353040" + "version": "0.31.34.60546", + "templateHash": "5493266151487858395" }, "name": "API Management Service Named Values", "description": "This module deploys an API Management Service Named Value.", @@ -80,10 +80,7 @@ "displayName": "[parameters('displayName')]", "value": "[if(variables('keyVaultEmpty'), parameters('value'), null())]", "keyVault": "[if(not(variables('keyVaultEmpty')), parameters('keyVault'), null())]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { diff --git a/avm/res/api-management/service/policy/main.json b/avm/res/api-management/service/policy/main.json index dd3c7eab82..d4d4505da4 100644 --- a/avm/res/api-management/service/policy/main.json +++ b/avm/res/api-management/service/policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "9395795206748286282" + "version": "0.31.34.60546", + "templateHash": "957115286202001780" }, "name": "API Management Service Policies", "description": "This module deploys an API Management Service Policy.", diff --git a/avm/res/api-management/service/portalsetting/main.json b/avm/res/api-management/service/portalsetting/main.json index d68c8ed791..505ef1bb18 100644 --- a/avm/res/api-management/service/portalsetting/main.json +++ b/avm/res/api-management/service/portalsetting/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14869704072680236257" + "version": "0.31.34.60546", + "templateHash": "9587521329160400551" }, "name": "API Management Service Portal Settings", "description": "This module deploys an API Management Service Portal Setting.", diff --git a/avm/res/api-management/service/product/api/main.json b/avm/res/api-management/service/product/api/main.json index 5603f9f789..f959bf4191 100644 --- a/avm/res/api-management/service/product/api/main.json +++ b/avm/res/api-management/service/product/api/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "602104798329438871" + "version": "0.31.34.60546", + "templateHash": "11213919899113582129" }, "name": "API Management Service Products APIs", "description": "This module deploys an API Management Service Product API.", diff --git a/avm/res/api-management/service/product/group/main.json b/avm/res/api-management/service/product/group/main.json index 28d5460152..0dcdd2026c 100644 --- a/avm/res/api-management/service/product/group/main.json +++ b/avm/res/api-management/service/product/group/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "5238408376918932137" + "version": "0.31.34.60546", + "templateHash": "10245602090275457578" }, "name": "API Management Service Products Groups", "description": "This module deploys an API Management Service Product Group.", diff --git a/avm/res/api-management/service/product/main.json b/avm/res/api-management/service/product/main.json index 892a25de5c..aa02572e7d 100644 --- a/avm/res/api-management/service/product/main.json +++ b/avm/res/api-management/service/product/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "8029364311033748838" + "version": "0.31.34.60546", + "templateHash": "3551579457056086397" }, "name": "API Management Service Products", "description": "This module deploys an API Management Service Product.", @@ -133,8 +133,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "602104798329438871" + "version": "0.31.34.60546", + "templateHash": "11213919899113582129" }, "name": "API Management Service Products APIs", "description": "This module deploys an API Management Service Product API.", @@ -223,8 +223,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "5238408376918932137" + "version": "0.31.34.60546", + "templateHash": "10245602090275457578" }, "name": "API Management Service Products Groups", "description": "This module deploys an API Management Service Product Group.", diff --git a/avm/res/api-management/service/subscription/main.json b/avm/res/api-management/service/subscription/main.json index 6abc772cc3..2c53fdfa76 100644 --- a/avm/res/api-management/service/subscription/main.json +++ b/avm/res/api-management/service/subscription/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "16082435269276611452" + "version": "0.31.34.60546", + "templateHash": "17857709197993310769" }, "name": "API Management Service Subscriptions", "description": "This module deploys an API Management Service Subscription.", @@ -94,10 +94,7 @@ "secondaryKey": "[parameters('secondaryKey')]", "state": "[parameters('state')]", "allowTracing": "[parameters('allowTracing')]" - }, - "dependsOn": [ - "service" - ] + } } }, "outputs": { diff --git a/avm/res/app-configuration/configuration-store/README.md b/avm/res/app-configuration/configuration-store/README.md index e7a84828bf..1c56ccbbc6 100644 --- a/avm/res/app-configuration/configuration-store/README.md +++ b/avm/res/app-configuration/configuration-store/README.md @@ -1324,15 +1324,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1341,6 +1339,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/app-configuration/configuration-store/key-value/main.json b/avm/res/app-configuration/configuration-store/key-value/main.json index 58dc82fcea..4dca71c4cb 100644 --- a/avm/res/app-configuration/configuration-store/key-value/main.json +++ b/avm/res/app-configuration/configuration-store/key-value/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11258786733278014615" + "version": "0.30.23.60470", + "templateHash": "7176115037834080970" }, "name": "App Configuration Stores Key Values", "description": "This module deploys an App Configuration Store Key Value.", diff --git a/avm/res/app-configuration/configuration-store/main.bicep b/avm/res/app-configuration/configuration-store/main.bicep index c989fc47a0..5092c71d32 100644 --- a/avm/res/app-configuration/configuration-store/main.bicep +++ b/avm/res/app-configuration/configuration-store/main.bicep @@ -209,7 +209,7 @@ module configurationStore_keyValues 'key-value/main.bicep' = [ } ] -module configurationStore_replicas 'replicas/main.bicep' = [ +module configurationStore_replicas 'replica/main.bicep' = [ for (replicaLocation, index) in (replicaLocations ?? []): { name: '${uniqueString(deployment().name, location)}-AppConfig-Replicas-${index}' params: { @@ -447,7 +447,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/app-configuration/configuration-store/main.json b/avm/res/app-configuration/configuration-store/main.json index acbc9026c6..e782f1670c 100644 --- a/avm/res/app-configuration/configuration-store/main.json +++ b/avm/res/app-configuration/configuration-store/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12024958859514872959" + "version": "0.30.23.60470", + "templateHash": "1061724596337882078" }, "name": "App Configuration Stores", "description": "This module deploys an App Configuration Store.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -838,8 +838,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11258786733278014615" + "version": "0.30.23.60470", + "templateHash": "7176115037834080970" }, "name": "App Configuration Stores Key Values", "description": "This module deploys an App Configuration Store Key Value.", @@ -959,8 +959,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12501157551760596905" + "version": "0.30.23.60470", + "templateHash": "7558745915280433021" }, "name": "App Configuration Replicas", "description": "This module deploys an App Configuration Replica.", @@ -976,13 +976,13 @@ "appConfigurationName": { "type": "string", "metadata": { - "description": "Optional. The name of the parent app configuration store." + "description": "Conditional. The name of the parent app configuration store. Required if the template is used in a standalone deployment." } }, "replicaLocation": { "type": "string", "metadata": { - "description": "Optional. Location of the replica." + "description": "Required. Location of the replica." } } }, diff --git a/avm/res/app-configuration/configuration-store/replicas/README.md b/avm/res/app-configuration/configuration-store/replica/README.md similarity index 84% rename from avm/res/app-configuration/configuration-store/replicas/README.md rename to avm/res/app-configuration/configuration-store/replica/README.md index aedae3e7b8..dbfdc26d3f 100644 --- a/avm/res/app-configuration/configuration-store/replicas/README.md +++ b/avm/res/app-configuration/configuration-store/replica/README.md @@ -21,13 +21,13 @@ This module deploys an App Configuration Replica. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | Name of the replica. | +| [`replicaLocation`](#parameter-replicalocation) | string | Location of the replica. | -**Optional parameters** +**Conditional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | -| [`appConfigurationName`](#parameter-appconfigurationname) | string | The name of the parent app configuration store. | -| [`replicaLocation`](#parameter-replicalocation) | string | Location of the replica. | +| [`appConfigurationName`](#parameter-appconfigurationname) | string | The name of the parent app configuration store. Required if the template is used in a standalone deployment. | ### Parameter: `name` @@ -36,16 +36,16 @@ Name of the replica. - Required: Yes - Type: string -### Parameter: `appConfigurationName` +### Parameter: `replicaLocation` -The name of the parent app configuration store. +Location of the replica. - Required: Yes - Type: string -### Parameter: `replicaLocation` +### Parameter: `appConfigurationName` -Location of the replica. +The name of the parent app configuration store. Required if the template is used in a standalone deployment. - Required: Yes - Type: string diff --git a/avm/res/app-configuration/configuration-store/replicas/main.bicep b/avm/res/app-configuration/configuration-store/replica/main.bicep similarity index 82% rename from avm/res/app-configuration/configuration-store/replicas/main.bicep rename to avm/res/app-configuration/configuration-store/replica/main.bicep index 43e37d6d8d..d78b06cc51 100644 --- a/avm/res/app-configuration/configuration-store/replicas/main.bicep +++ b/avm/res/app-configuration/configuration-store/replica/main.bicep @@ -5,10 +5,10 @@ metadata owner = 'Azure/module-maintainers' @description('Required. Name of the replica.') param name string -@description('Optional. The name of the parent app configuration store.') +@description('Conditional. The name of the parent app configuration store. Required if the template is used in a standalone deployment.') param appConfigurationName string -@description('Optional. Location of the replica.') +@description('Required. Location of the replica.') param replicaLocation string resource appConfiguration 'Microsoft.AppConfiguration/configurationStores@2023-03-01' existing = { diff --git a/avm/res/app-configuration/configuration-store/replicas/main.json b/avm/res/app-configuration/configuration-store/replica/main.json similarity index 85% rename from avm/res/app-configuration/configuration-store/replicas/main.json rename to avm/res/app-configuration/configuration-store/replica/main.json index 220da65163..e4c0a9dacb 100644 --- a/avm/res/app-configuration/configuration-store/replicas/main.json +++ b/avm/res/app-configuration/configuration-store/replica/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12501157551760596905" + "version": "0.30.23.60470", + "templateHash": "7558745915280433021" }, "name": "App Configuration Replicas", "description": "This module deploys an App Configuration Replica.", @@ -21,13 +21,13 @@ "appConfigurationName": { "type": "string", "metadata": { - "description": "Optional. The name of the parent app configuration store." + "description": "Conditional. The name of the parent app configuration store. Required if the template is used in a standalone deployment." } }, "replicaLocation": { "type": "string", "metadata": { - "description": "Optional. Location of the replica." + "description": "Required. Location of the replica." } } }, diff --git a/avm/res/app/job/README.md b/avm/res/app/job/README.md index 51e3119966..32d9a19e7b 100644 --- a/avm/res/app/job/README.md +++ b/avm/res/app/job/README.md @@ -1114,7 +1114,6 @@ HTTPGet specifies the http request to perform. | :-- | :-- | :-- | | [`path`](#parameter-containersprobeshttpgetpath) | string | Path to access on the HTTP server. | | [`port`](#parameter-containersprobeshttpgetport) | int | Name of the port to access on the container. If not specified, the containerPort is used. | -| [`scheme`](#parameter-containersprobeshttpgetscheme) | string | Scheme to use for connecting to the host. Defaults to HTTP. | **Optional parameters** @@ -1122,6 +1121,7 @@ HTTPGet specifies the http request to perform. | :-- | :-- | :-- | | [`host`](#parameter-containersprobeshttpgethost) | string | Host name to connect to, defaults to the pod IP. | | [`httpHeaders`](#parameter-containersprobeshttpgethttpheaders) | array | Custom headers to set in the request. | +| [`scheme`](#parameter-containersprobeshttpgetscheme) | string | Scheme to use for connecting to the host. Defaults to HTTP. | ### Parameter: `containers.probes.httpGet.path` @@ -1137,20 +1137,6 @@ Name of the port to access on the container. If not specified, the containerPort - Required: Yes - Type: int -### Parameter: `containers.probes.httpGet.scheme` - -Scheme to use for connecting to the host. Defaults to HTTP. - -- Required: No -- Type: string -- Allowed: - ```Bicep - [ - 'HTTP' - 'HTTPS' - ] - ``` - ### Parameter: `containers.probes.httpGet.host` Host name to connect to, defaults to the pod IP. @@ -1186,6 +1172,20 @@ The header field value. - Required: Yes - Type: string +### Parameter: `containers.probes.httpGet.scheme` + +Scheme to use for connecting to the host. Defaults to HTTP. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'HTTP' + 'HTTPS' + ] + ``` + ### Parameter: `containers.probes.initialDelaySeconds` Number of seconds after the container has started before liveness probes are initiated. Defaults to 0 seconds. @@ -1218,13 +1218,15 @@ TCPSocket specifies an action involving a TCP port. | Parameter | Type | Description | | :-- | :-- | :-- | +| [`host`](#parameter-containersprobestcpsockethost) | string | Host name to connect to, defaults to the pod IP. | | [`port`](#parameter-containersprobestcpsocketport) | int | Name of the port to access on the container. If not specified, the containerPort is used. | -**Optional parameters** +### Parameter: `containers.probes.tcpSocket.host` -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`host`](#parameter-containersprobestcpsockethost) | string | Host name to connect to, defaults to the pod IP. | +Host name to connect to, defaults to the pod IP. + +- Required: Yes +- Type: string ### Parameter: `containers.probes.tcpSocket.port` @@ -1233,13 +1235,6 @@ Name of the port to access on the container. If not specified, the containerPort - Required: Yes - Type: int -### Parameter: `containers.probes.tcpSocket.host` - -Host name to connect to, defaults to the pod IP. - -- Required: Yes -- Type: string - ### Parameter: `containers.probes.terminationGracePeriodSeconds` Duration in seconds the pod needs to terminate gracefully upon probe failure. This is an alpha field and requires enabling ProbeTerminationGracePeriod feature gate. @@ -1266,11 +1261,6 @@ The resources to allocate to the container. | Parameter | Type | Description | | :-- | :-- | :-- | | [`cpu`](#parameter-containersresourcescpu) | string | The CPU limit of the container in cores. | - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | | [`memory`](#parameter-containersresourcesmemory) | string | The required memory. | ### Parameter: `containers.resources.cpu` @@ -1395,6 +1385,12 @@ Scaling configurations for event driven jobs. - Required: Yes - Type: object +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`rules`](#parameter-eventtriggerconfigscalerules) | array | Scaling rules for the job. | + **Optional parameters** | Parameter | Type | Description | @@ -1402,28 +1398,6 @@ Scaling configurations for event driven jobs. | [`maxExecutions`](#parameter-eventtriggerconfigscalemaxexecutions) | int | Maximum number of job executions that are created for a trigger, default 100. | | [`minExecutions`](#parameter-eventtriggerconfigscaleminexecutions) | int | Minimum number of job executions that are created for a trigger, default 0. | | [`pollingInterval`](#parameter-eventtriggerconfigscalepollinginterval) | int | Interval to check each event source in seconds. Defaults to 30s. | -| [`rules`](#parameter-eventtriggerconfigscalerules) | array | Scaling rules for the job. | - -### Parameter: `eventTriggerConfig.scale.maxExecutions` - -Maximum number of job executions that are created for a trigger, default 100. - -- Required: No -- Type: int - -### Parameter: `eventTriggerConfig.scale.minExecutions` - -Minimum number of job executions that are created for a trigger, default 0. - -- Required: No -- Type: int - -### Parameter: `eventTriggerConfig.scale.pollingInterval` - -Interval to check each event source in seconds. Defaults to 30s. - -- Required: No -- Type: int ### Parameter: `eventTriggerConfig.scale.rules` @@ -1454,15 +1428,52 @@ Scaling rules for the job. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`auth`](#parameter-eventtriggerconfigscalerulesauth) | array | Authentication secrets for the scale rule. | +| [`metadata`](#parameter-eventtriggerconfigscalerulesmetadata) | object | Metadata properties to describe the scale rule. | | [`name`](#parameter-eventtriggerconfigscalerulesname) | string | The name of the scale rule. | +| [`type`](#parameter-eventtriggerconfigscalerulestype) | string | The type of the rule. | **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | -| [`metadata`](#parameter-eventtriggerconfigscalerulesmetadata) | object | Metadata properties to describe the scale rule. | -| [`type`](#parameter-eventtriggerconfigscalerulestype) | string | The type of the rule. | +| [`auth`](#parameter-eventtriggerconfigscalerulesauth) | array | Authentication secrets for the scale rule. | + +### Parameter: `eventTriggerConfig.scale.rules.metadata` + +Metadata properties to describe the scale rule. + +- Required: Yes +- Type: object +- Example: + ```Bicep + { + "// for type azure-queue + { + queueName: 'default' + storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/myStorageAccount' + }" + } + ``` + +### Parameter: `eventTriggerConfig.scale.rules.name` + +The name of the scale rule. + +- Required: Yes +- Type: string + +### Parameter: `eventTriggerConfig.scale.rules.type` + +The type of the rule. + +- Required: Yes +- Type: string +- Example: + ```Bicep + "azure-servicebus" + "azure-queue" + "redis" + ``` ### Parameter: `eventTriggerConfig.scale.rules.auth` @@ -1492,42 +1503,26 @@ Trigger Parameter that uses the secret. - Required: Yes - Type: string -### Parameter: `eventTriggerConfig.scale.rules.name` +### Parameter: `eventTriggerConfig.scale.maxExecutions` -The name of the scale rule. +Maximum number of job executions that are created for a trigger, default 100. -- Required: Yes -- Type: string +- Required: No +- Type: int -### Parameter: `eventTriggerConfig.scale.rules.metadata` +### Parameter: `eventTriggerConfig.scale.minExecutions` -Metadata properties to describe the scale rule. +Minimum number of job executions that are created for a trigger, default 0. -- Required: Yes -- Type: object -- Example: - ```Bicep - { - "// for type azure-queue - { - queueName: 'default' - storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/myStorageAccount' - }" - } - ``` +- Required: No +- Type: int -### Parameter: `eventTriggerConfig.scale.rules.type` +### Parameter: `eventTriggerConfig.scale.pollingInterval` -The type of the rule. +Interval to check each event source in seconds. Defaults to 30s. -- Required: Yes -- Type: string -- Example: - ```Bicep - "azure-servicebus" - "azure-queue" - "redis" - ``` +- Required: No +- Type: int ### Parameter: `eventTriggerConfig.parallelism` @@ -1636,90 +1631,46 @@ List of specialized containers that run before app containers. | Parameter | Type | Description | | :-- | :-- | :-- | +| [`args`](#parameter-initcontainersargs) | array | Container start command arguments. | +| [`command`](#parameter-initcontainerscommand) | array | Container start command. | | [`image`](#parameter-initcontainersimage) | string | The image of the container. | | [`name`](#parameter-initcontainersname) | string | The name of the container. | -| [`resources`](#parameter-initcontainersresources) | object | Container resource requirements. | **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | -| [`args`](#parameter-initcontainersargs) | array | Container start command arguments. | -| [`command`](#parameter-initcontainerscommand) | array | Container start command. | | [`env`](#parameter-initcontainersenv) | array | The environment variables to set in the container. | +| [`resources`](#parameter-initcontainersresources) | object | Container resource requirements. | | [`volumeMounts`](#parameter-initcontainersvolumemounts) | array | The volume mounts to attach to the container. | -### Parameter: `initContainers.image` +### Parameter: `initContainers.args` -The image of the container. +Container start command arguments. - Required: Yes -- Type: string +- Type: array -### Parameter: `initContainers.name` +### Parameter: `initContainers.command` -The name of the container. +Container start command. - Required: Yes -- Type: string - -### Parameter: `initContainers.resources` - -Container resource requirements. - -- Required: No -- Type: object - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`cpu`](#parameter-initcontainersresourcescpu) | string | The CPU limit of the container in cores. | - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`memory`](#parameter-initcontainersresourcesmemory) | string | The required memory. | +- Type: array -### Parameter: `initContainers.resources.cpu` +### Parameter: `initContainers.image` -The CPU limit of the container in cores. +The image of the container. - Required: Yes - Type: string -- Example: - ```Bicep - '0.25' - '1' - ``` -### Parameter: `initContainers.resources.memory` +### Parameter: `initContainers.name` -The required memory. +The name of the container. - Required: Yes - Type: string -- Example: - ```Bicep - '250Mb' - '1.5Gi' - '1500Mi' - ``` - -### Parameter: `initContainers.args` - -Container start command arguments. - -- Required: Yes -- Type: array - -### Parameter: `initContainers.command` - -Container start command. - -- Required: Yes -- Type: array ### Parameter: `initContainers.env` @@ -1775,6 +1726,45 @@ The environment variable value. Required if `secretRef` is null. - Required: No - Type: string +### Parameter: `initContainers.resources` + +Container resource requirements. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`cpu`](#parameter-initcontainersresourcescpu) | string | The CPU limit of the container in cores. | +| [`memory`](#parameter-initcontainersresourcesmemory) | string | The required memory. | + +### Parameter: `initContainers.resources.cpu` + +The CPU limit of the container in cores. + +- Required: Yes +- Type: string +- Example: + ```Bicep + '0.25' + '1' + ``` + +### Parameter: `initContainers.resources.memory` + +The required memory. + +- Required: Yes +- Type: string +- Example: + ```Bicep + '250Mb' + '1.5Gi' + '1500Mi' + ``` + ### Parameter: `initContainers.volumeMounts` The volume mounts to attach to the container. diff --git a/avm/res/app/job/main.bicep b/avm/res/app/job/main.bicep index 974873afd2..b86b96a6ae 100644 --- a/avm/res/app/job/main.bicep +++ b/avm/res/app/job/main.bicep @@ -429,7 +429,7 @@ type containerProbeType = { @maxValue(65535) port: int - @description('Required. Scheme to use for connecting to the host. Defaults to HTTP.') + @description('Optional. Scheme to use for connecting to the host. Defaults to HTTP.') scheme: ('HTTP' | 'HTTPS')? }? @@ -450,7 +450,7 @@ type containerProbeType = { @description('Optional. TCPSocket specifies an action involving a TCP port.') tcpSocket: { - @description('Optional. Host name to connect to, defaults to the pod IP.') + @description('Required. Host name to connect to, defaults to the pod IP.') host: string @description('Required. Name of the port to access on the container. If not specified, the containerPort is used.') @@ -483,7 +483,7 @@ type containerResourceType = { }) cpu: string - @description('Optional. The required memory.') + @description('Required. The required memory.') @metadata({ example: ''' '250Mb' @@ -551,7 +551,7 @@ type jobScaleType = { @description('Optional. Interval to check each event source in seconds. Defaults to 30s.') pollingInterval: int? - @description('Optional. Scaling rules for the job.') + @description('Required. Scaling rules for the job.') @metadata({ example: ''' [ @@ -572,7 +572,7 @@ type jobScaleType = { ''' }) rules: { - @description('Required. Authentication secrets for the scale rule.') + @description('Optional. Authentication secrets for the scale rule.') auth: { @description('Required. Name of the secret from which to pull the auth params.') secretRef: string @@ -581,7 +581,7 @@ type jobScaleType = { triggerParameter: string }[]? - @description('Optional. Metadata properties to describe the scale rule.') + @description('Required. Metadata properties to describe the scale rule.') @metadata({ example: ''' { @@ -598,7 +598,7 @@ type jobScaleType = { @description('Required. The name of the scale rule.') name: string - @description('Optional. The type of the rule.') + @description('Required. The type of the rule.') @metadata({ example: ''' "azure-servicebus" @@ -611,10 +611,10 @@ type jobScaleType = { } type initContainerType = { - @description('Optional. Container start command arguments.') + @description('Required. Container start command arguments.') args: string[] - @description('Optional. Container start command.') + @description('Required. Container start command.') command: string[] @description('Optional. The environment variables to set in the container.') @@ -640,7 +640,7 @@ type initContainerType = { @description('Required. The name of the container.') name: string - @description('Required. Container resource requirements.') + @description('Optional. Container resource requirements.') resources: containerResourceType? @description('Optional. The volume mounts to attach to the container.') diff --git a/avm/res/app/job/main.json b/avm/res/app/job/main.json index b0a56e15a3..7a867b950f 100644 --- a/avm/res/app/job/main.json +++ b/avm/res/app/job/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15353778009725544189" + "version": "0.30.23.60470", + "templateHash": "12763012216760511641" }, "name": "Container App Jobs", "description": "This module deploys a Container App Job.", @@ -353,7 +353,7 @@ ], "nullable": true, "metadata": { - "description": "Required. Scheme to use for connecting to the host. Defaults to HTTP." + "description": "Optional. Scheme to use for connecting to the host. Defaults to HTTP." } } }, @@ -395,7 +395,7 @@ "host": { "type": "string", "metadata": { - "description": "Optional. Host name to connect to, defaults to the pod IP." + "description": "Required. Host name to connect to, defaults to the pod IP." } }, "port": { @@ -457,7 +457,7 @@ "type": "string", "metadata": { "example": " '250Mb'\n '1.5Gi'\n '1500Mi'\n ", - "description": "Optional. The required memory." + "description": "Required. The required memory." } } } @@ -606,14 +606,14 @@ }, "nullable": true, "metadata": { - "description": "Required. Authentication secrets for the scale rule." + "description": "Optional. Authentication secrets for the scale rule." } }, "metadata": { "type": "object", "metadata": { "example": " {\n \"// for type azure-queue\n {\n queueName: 'default'\n storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/myStorageAccount'\n }\"\n }\n ", - "description": "Optional. Metadata properties to describe the scale rule." + "description": "Required. Metadata properties to describe the scale rule." } }, "name": { @@ -626,14 +626,14 @@ "type": "string", "metadata": { "example": " \"azure-servicebus\"\n \"azure-queue\"\n \"redis\"\n ", - "description": "Optional. The type of the rule." + "description": "Required. The type of the rule." } } } }, "metadata": { "example": " [\n // for type azure-queue\n {\n name: 'myrule'\n type: 'azure-queue'\n metadata: {\n queueName: 'default'\n storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/myStorageAccount'\n }\n auth: {\n secretRef: 'mysecret'\n triggerParameter: 'queueName'\n }\n }\n ]\n ", - "description": "Optional. Scaling rules for the job." + "description": "Required. Scaling rules for the job." } } } @@ -647,7 +647,7 @@ "type": "string" }, "metadata": { - "description": "Optional. Container start command arguments." + "description": "Required. Container start command arguments." } }, "command": { @@ -656,7 +656,7 @@ "type": "string" }, "metadata": { - "description": "Optional. Container start command." + "description": "Required. Container start command." } }, "env": { @@ -686,7 +686,7 @@ "$ref": "#/definitions/containerResourceType", "nullable": true, "metadata": { - "description": "Required. Container resource requirements." + "description": "Optional. Container resource requirements." } }, "volumeMounts": { diff --git a/avm/res/app/managed-environment/README.md b/avm/res/app/managed-environment/README.md index 3d5b5191c4..45e2659dca 100644 --- a/avm/res/app/managed-environment/README.md +++ b/avm/res/app/managed-environment/README.md @@ -174,6 +174,11 @@ module managedEnvironment 'br/public:avm/res/app/managed-environment:' name: 'amemax001' // Non-required parameters appInsightsConnectionString: '' + certificateKeyVaultProperties: { + identityResourceId: '' + keyVaultUrl: '' + } + dnsSuffix: 'contoso.com' dockerBridgeCidr: '172.16.0.1/28' infrastructureResourceGroupName: '' infrastructureSubnetId: '' @@ -276,6 +281,15 @@ module managedEnvironment 'br/public:avm/res/app/managed-environment:' "appInsightsConnectionString": { "value": "" }, + "certificateKeyVaultProperties": { + "value": { + "identityResourceId": "", + "keyVaultUrl": "" + } + }, + "dnsSuffix": { + "value": "contoso.com" + }, "dockerBridgeCidr": { "value": "172.16.0.1/28" }, @@ -400,6 +414,11 @@ param logAnalyticsWorkspaceResourceId = '' param name = 'amemax001' // Non-required parameters param appInsightsConnectionString = '' +param certificateKeyVaultProperties = { + identityResourceId: '' + keyVaultUrl: '' +} +param dnsSuffix = 'contoso.com' param dockerBridgeCidr = '172.16.0.1/28' param infrastructureResourceGroupName = '' param infrastructureSubnetId = '' @@ -712,6 +731,7 @@ param workloadProfiles = [ | Parameter | Type | Description | | :-- | :-- | :-- | | [`appInsightsConnectionString`](#parameter-appinsightsconnectionstring) | securestring | Application Insights connection string. | +| [`certificateKeyVaultProperties`](#parameter-certificatekeyvaultproperties) | object | A key vault reference to the certificate to use for the custom domain. | | [`certificatePassword`](#parameter-certificatepassword) | securestring | Password of the certificate used by the custom domain. | | [`certificateValue`](#parameter-certificatevalue) | securestring | Certificate to use for the custom domain. PFX or PEM. | | [`daprAIConnectionString`](#parameter-dapraiconnectionstring) | securestring | Application Insights connection string used by Dapr to export Service to Service communication telemetry. | @@ -807,6 +827,34 @@ Application Insights connection string. - Type: securestring - Default: `''` +### Parameter: `certificateKeyVaultProperties` + +A key vault reference to the certificate to use for the custom domain. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`identityResourceId`](#parameter-certificatekeyvaultpropertiesidentityresourceid) | string | The resource ID of the identity. This is the identity that will be used to access the key vault. | +| [`keyVaultUrl`](#parameter-certificatekeyvaultpropertieskeyvaulturl) | string | A key vault URL referencing the wildcard certificate that will be used for the custom domain. | + +### Parameter: `certificateKeyVaultProperties.identityResourceId` + +The resource ID of the identity. This is the identity that will be used to access the key vault. + +- Required: Yes +- Type: string + +### Parameter: `certificateKeyVaultProperties.keyVaultUrl` + +A key vault URL referencing the wildcard certificate that will be used for the custom domain. + +- Required: Yes +- Type: string + ### Parameter: `certificatePassword` Password of the certificate used by the custom domain. diff --git a/avm/res/app/managed-environment/main.bicep b/avm/res/app/managed-environment/main.bicep index 02a51e0485..32283e9539 100644 --- a/avm/res/app/managed-environment/main.bicep +++ b/avm/res/app/managed-environment/main.bicep @@ -67,6 +67,9 @@ param certificatePassword string = '' @secure() param certificateValue string = '' +@description('Optional. A key vault reference to the certificate to use for the custom domain.') +param certificateKeyVaultProperties certificateKeyVaultPropertiesType + @description('Optional. DNS suffix for the environment domain.') param dnsSuffix string = '' @@ -171,6 +174,12 @@ resource managedEnvironment 'Microsoft.App/managedEnvironments@2024-02-02-previe certificatePassword: certificatePassword certificateValue: !empty(certificateValue) ? certificateValue : null dnsSuffix: dnsSuffix + certificateKeyVaultProperties: !empty(certificateKeyVaultProperties) + ? { + identity: certificateKeyVaultProperties!.identityResourceId + keyVaultUrl: certificateKeyVaultProperties!.keyVaultUrl + } + : null } openTelemetryConfiguration: !empty(openTelemetryConfiguration) ? openTelemetryConfiguration : null peerTrafficConfiguration: { @@ -315,6 +324,14 @@ type roleAssignmentType = { delegatedManagedIdentityResourceId: string? }[]? +type certificateKeyVaultPropertiesType = { + @description('Required. The resource ID of the identity. This is the identity that will be used to access the key vault.') + identityResourceId: string + + @description('Required. A key vault URL referencing the wildcard certificate that will be used for the custom domain.') + keyVaultUrl: string +}? + type storageType = { @description('Required. Access mode for storage: "ReadOnly" or "ReadWrite".') accessMode: ('ReadOnly' | 'ReadWrite') diff --git a/avm/res/app/managed-environment/main.json b/avm/res/app/managed-environment/main.json index 867286f2d8..ae3d233828 100644 --- a/avm/res/app/managed-environment/main.json +++ b/avm/res/app/managed-environment/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5062482221653261403" + "version": "0.30.23.60470", + "templateHash": "2437611645646369754" }, "name": "App ManagedEnvironments", "description": "This module deploys an App Managed Environment (also known as a Container App Environment).", @@ -134,6 +134,24 @@ }, "nullable": true }, + "certificateKeyVaultPropertiesType": { + "type": "object", + "properties": { + "identityResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the identity. This is the identity that will be used to access the key vault." + } + }, + "keyVaultUrl": { + "type": "string", + "metadata": { + "description": "Required. A key vault URL referencing the wildcard certificate that will be used for the custom domain." + } + } + }, + "nullable": true + }, "storageType": { "type": "array", "items": { @@ -313,6 +331,12 @@ "description": "Optional. Certificate to use for the custom domain. PFX or PEM." } }, + "certificateKeyVaultProperties": { + "$ref": "#/definitions/certificateKeyVaultPropertiesType", + "metadata": { + "description": "Optional. A key vault reference to the certificate to use for the custom domain." + } + }, "dnsSuffix": { "type": "string", "defaultValue": "", @@ -441,7 +465,8 @@ "customDomainConfiguration": { "certificatePassword": "[parameters('certificatePassword')]", "certificateValue": "[if(not(empty(parameters('certificateValue'))), parameters('certificateValue'), null())]", - "dnsSuffix": "[parameters('dnsSuffix')]" + "dnsSuffix": "[parameters('dnsSuffix')]", + "certificateKeyVaultProperties": "[if(not(empty(parameters('certificateKeyVaultProperties'))), createObject('identity', parameters('certificateKeyVaultProperties').identityResourceId, 'keyVaultUrl', parameters('certificateKeyVaultProperties').keyVaultUrl), null())]" }, "openTelemetryConfiguration": "[if(not(empty(parameters('openTelemetryConfiguration'))), parameters('openTelemetryConfiguration'), null())]", "peerTrafficConfiguration": { diff --git a/avm/res/app/managed-environment/tests/e2e/max/dependencies.bicep b/avm/res/app/managed-environment/tests/e2e/max/dependencies.bicep index 6c836f75d6..becf14af2e 100644 --- a/avm/res/app/managed-environment/tests/e2e/max/dependencies.bicep +++ b/avm/res/app/managed-environment/tests/e2e/max/dependencies.bicep @@ -13,6 +13,19 @@ param virtualNetworkName string @description('Required. The name of the Managed Identity to create.') param managedIdentityName string +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Deployment Script to create for the Certificate generation.') +param certDeploymentScriptName string + +@secure() +@description('Required. The name for the SSL certificate.') +param certname string + +var certPWSecretName = 'pfxCertificatePassword' +var certSecretName = 'pfxBase64Certificate' + @description('Required. The name of the Storage Account to create.') param storageAccountName string @@ -80,6 +93,55 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- location: location } +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: null + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${managedIdentity.name}-KeyVault-Admin-RoleAssignment') + scope: keyVault + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '00482a5a-887f-4fb3-b363-3b7fe8e74483' + ) // Key Vault Administrator + principalType: 'ServicePrincipal' + } +} + +resource certDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: certDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '8.0' + retentionInterval: 'P1D' + arguments: '-KeyVaultName "${keyVault.name}" -CertName "${certname}" -CertSubjectName "CN=*.contoso.com"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-CertificateInKeyVault.ps1') + } +} + resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { name: storageAccountName location: location @@ -134,6 +196,21 @@ output managedIdentityPrincipalId string = managedIdentity.properties.principalI @description('The resource ID of the created Managed Identity.') output managedIdentityResourceId string = managedIdentity.id +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URI of the created Key Vault.') +output keyVaultUri string = keyVault.properties.vaultUri + +@description('The URL of the created certificate.') +output certificateSecretUrl string = certDeploymentScript.properties.outputs.secretUrl + +@description('The name of the certification password secret.') +output certPWSecretName string = certPWSecretName + +@description('The name of the certification secret.') +output certSecretName string = certSecretName + @description('The Connection String of the created Application Insights Component.') output appInsightsConnectionString string = appInsightsComponent.properties.ConnectionString diff --git a/avm/res/app/managed-environment/tests/e2e/max/main.test.bicep b/avm/res/app/managed-environment/tests/e2e/max/main.test.bicep index 582c1734c7..b915042b75 100644 --- a/avm/res/app/managed-environment/tests/e2e/max/main.test.bicep +++ b/avm/res/app/managed-environment/tests/e2e/max/main.test.bicep @@ -38,6 +38,9 @@ module nestedDependencies 'dependencies.bicep' = { virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' location: resourceLocation managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + certname: 'dep-${namePrefix}-cert-${serviceShort}' + certDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}' appInsightsComponentName: 'dep-${namePrefix}-appinsights-${serviceShort}' storageAccountName: 'dep${namePrefix}sa${serviceShort}' } @@ -66,6 +69,11 @@ module testDeployment '../../../main.bicep' = [ } ] internal: true + dnsSuffix: 'contoso.com' + certificateKeyVaultProperties: { + identityResourceId: nestedDependencies.outputs.managedIdentityResourceId + keyVaultUrl: '${nestedDependencies.outputs.keyVaultUri}secrets/${split(nestedDependencies.outputs.certificateSecretUrl, '/')[4]}' + } dockerBridgeCidr: '172.16.0.1/28' peerTrafficEncryption: true platformReservedCidr: '172.17.17.0/24' diff --git a/avm/res/automation/automation-account/README.md b/avm/res/automation/automation-account/README.md index 549a0c129e..25662fa93d 100644 --- a/avm/res/automation/automation-account/README.md +++ b/avm/res/automation/automation-account/README.md @@ -246,9 +246,11 @@ module automationAccount 'br/public:avm/res/automation/automation-account:' + plan: { + product: 'OMSGallery/Updates' + publisher: 'Microsoft' + } } ] jobSchedules: [ @@ -507,9 +509,11 @@ module automationAccount 'br/public:avm/res/automation/automation-account:", + "plan": { + "product": "OMSGallery/Updates", + "publisher": "Microsoft" + } } ] }, @@ -784,9 +788,11 @@ param diagnosticSettings = [ param disableLocalAuth = true param gallerySolutions = [ { - name: 'Updates' - product: 'OMSGallery' - publisher: 'Microsoft' + name: '' + plan: { + product: 'OMSGallery/Updates' + publisher: 'Microsoft' + } } ] param jobSchedules = [ @@ -1025,9 +1031,10 @@ module automationAccount 'br/public:avm/res/automation/automation-account:' + plan: { + product: 'OMSGallery/Updates' + } } ] jobSchedules: [ @@ -1235,9 +1242,10 @@ module automationAccount 'br/public:avm/res/automation/automation-account:", + "plan": { + "product": "OMSGallery/Updates" + } } ] }, @@ -1461,9 +1469,10 @@ param diagnosticSettings = [ param disableLocalAuth = true param gallerySolutions = [ { - name: 'Updates' - product: 'OMSGallery' - publisher: 'Microsoft' + name: '' + plan: { + product: 'OMSGallery/Updates' + } } ] param jobSchedules = [ @@ -1686,7 +1695,6 @@ List of credentials to be created in the automation account. - Required: No - Type: array -- Default: `[]` **Required parameters** @@ -1796,7 +1804,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -1906,7 +1914,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -1947,7 +1955,61 @@ List of gallerySolutions to be created in the linked log analytics workspace. - Required: No - Type: array -- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-gallerysolutionsname) | string | Name of the solution.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.

    The solution type is case-sensitive. | +| [`plan`](#parameter-gallerysolutionsplan) | object | Plan for solution object supported by the OperationsManagement resource provider. | + +### Parameter: `gallerySolutions.name` + +Name of the solution.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.

    The solution type is case-sensitive. + +- Required: Yes +- Type: string + +### Parameter: `gallerySolutions.plan` + +Plan for solution object supported by the OperationsManagement resource provider. + +- Required: Yes +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`product`](#parameter-gallerysolutionsplanproduct) | string | The product name of the deployed solution.

    For Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.

    For a third party solution, it can be anything.

    This is case sensitive. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-gallerysolutionsplanname) | string | Name of the solution to be created.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, it can be anything.

    The solution type is case-sensitive.

    If not provided, the value of the `name` parameter will be used. | +| [`publisher`](#parameter-gallerysolutionsplanpublisher) | string | The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value. | + +### Parameter: `gallerySolutions.plan.product` + +The product name of the deployed solution.

    For Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.

    For a third party solution, it can be anything.

    This is case sensitive. + +- Required: Yes +- Type: string + +### Parameter: `gallerySolutions.plan.name` + +Name of the solution to be created.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, it can be anything.

    The solution type is case-sensitive.

    If not provided, the value of the `name` parameter will be used. + +- Required: No +- Type: string + +### Parameter: `gallerySolutions.plan.publisher` + +The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value. + +- Required: No +- Type: string ### Parameter: `jobSchedules` @@ -2021,7 +2083,7 @@ The managed identity definition for this resource. | Parameter | Type | Description | | :-- | :-- | :-- | | [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | ### Parameter: `managedIdentities.systemAssigned` @@ -2032,7 +2094,7 @@ Enables system assigned managed identity on the resource. ### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. - Required: No - Type: array @@ -2056,7 +2118,7 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file" for a Storage Account's Private Endpoints. | | [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | **Optional parameters** @@ -2081,7 +2143,7 @@ Configuration details for private endpoints. For security reasons, it is recomme ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". +The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file" for a Storage Account's Private Endpoints. - Required: Yes - Type: string @@ -2111,15 +2173,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -2128,6 +2188,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -2274,7 +2341,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -2284,7 +2351,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -2299,7 +2366,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -2310,7 +2377,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -2646,7 +2713,8 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | -| `br/public:avm/res/operations-management/solution:0.1.0` | Remote reference | +| `br/public:avm/res/operations-management/solution:0.3.0` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/automation/automation-account/credential/README.md b/avm/res/automation/automation-account/credential/README.md index fad726864a..98579563fa 100644 --- a/avm/res/automation/automation-account/credential/README.md +++ b/avm/res/automation/automation-account/credential/README.md @@ -20,7 +20,9 @@ This module deploys Azure Automation Account Credential. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`credentials`](#parameter-credentials) | array | The credential definition. | +| [`name`](#parameter-name) | string | Name of the Automation Account credential. | +| [`password`](#parameter-password) | securestring | Password of the credential. | +| [`userName`](#parameter-username) | string | The user name associated to the credential. | **Conditional parameters** @@ -28,66 +30,51 @@ This module deploys Azure Automation Account Credential. | :-- | :-- | :-- | | [`automationAccountName`](#parameter-automationaccountname) | string | The name of the parent Automation Account. Required if the template is used in a standalone deployment. | -### Parameter: `credentials` - -The credential definition. - -- Required: Yes -- Type: array - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`name`](#parameter-credentialsname) | string | Name of the Automation Account credential. | -| [`password`](#parameter-credentialspassword) | securestring | Password of the credential. | -| [`userName`](#parameter-credentialsusername) | string | The user name associated to the credential. | - **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | -| [`description`](#parameter-credentialsdescription) | string | Description of the credential. | +| [`description`](#parameter-description) | string | Description of the credential. | -### Parameter: `credentials.name` +### Parameter: `name` Name of the Automation Account credential. - Required: Yes - Type: string -### Parameter: `credentials.password` +### Parameter: `password` Password of the credential. - Required: Yes - Type: securestring -### Parameter: `credentials.userName` +### Parameter: `userName` The user name associated to the credential. - Required: Yes - Type: string -### Parameter: `credentials.description` +### Parameter: `automationAccountName` -Description of the credential. +The name of the parent Automation Account. Required if the template is used in a standalone deployment. -- Required: No +- Required: Yes - Type: string -### Parameter: `automationAccountName` +### Parameter: `description` -The name of the parent Automation Account. Required if the template is used in a standalone deployment. +Description of the credential. -- Required: Yes +- Required: No - Type: string ## Outputs | Output | Type | Description | | :-- | :-- | :-- | -| `name` | array | The names of the credentials associated to the automation account. | +| `name` | string | The name of the credential associated to the automation account. | | `resourceGroupName` | string | The resource group of the deployed credential. | -| `resourceId` | array | The resource IDs of the credentials associated to the automation account. | +| `resourceId` | string | The resource Id of the credential associated to the automation account. | diff --git a/avm/res/automation/automation-account/credential/main.bicep b/avm/res/automation/automation-account/credential/main.bicep index 63c73f52c6..fcd7df16e8 100644 --- a/avm/res/automation/automation-account/credential/main.bicep +++ b/avm/res/automation/automation-account/credential/main.bicep @@ -2,55 +2,41 @@ metadata name = 'Automation Account Credential' metadata description = 'This module deploys Azure Automation Account Credential.' metadata owner = 'Azure/module-maintainers' -@description('Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment.') +@sys.description('Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment.') param automationAccountName string -@description('Required. The credential definition.') -param credentials credentialType +@sys.description('Required. Name of the Automation Account credential.') +param name string + +@sys.description('Required. The user name associated to the credential.') +param userName string + +@sys.description('Required. Password of the credential.') +@secure() +param password string + +@sys.description('Optional. Description of the credential.') +param description string? resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = { name: automationAccountName } -resource automationAccount_credential 'Microsoft.Automation/automationAccounts/credentials@2023-11-01' = [ - for credential in credentials: { - name: credential.name - parent: automationAccount - properties: { - password: credential.password - userName: credential.userName - description: credential.?description ?? '' - } +resource credential 'Microsoft.Automation/automationAccounts/credentials@2023-11-01' = { + name: name + parent: automationAccount + properties: { + password: password + userName: userName + description: description ?? '' } -] +} -@description('The resource IDs of the credentials associated to the automation account.') -#disable-next-line outputs-should-not-contain-secrets // Does not return the secret, but just the ID -output resourceId array = [for index in range(0, length(credentials)): automationAccount_credential[index].id] +@sys.description('The resource Id of the credential associated to the automation account.') +output resourceId string = credential.id -@description('The names of the credentials associated to the automation account.') -#disable-next-line outputs-should-not-contain-secrets // Does not return the secret, but just the name -output name array = [for index in range(0, length(credentials)): automationAccount_credential[index].name] +@sys.description('The name of the credential associated to the automation account.') +output name string = credential.name -@description('The resource group of the deployed credential.') +@sys.description('The resource group of the deployed credential.') output resourceGroupName string = resourceGroup().name - -// ================ // -// Definitions // -// ================ // - -@export() -type credentialType = { - @description('Required. Name of the Automation Account credential.') - name: string - - @description('Required. The user name associated to the credential.') - userName: string - - @description('Required. Password of the credential.') - @secure() - password: string - - @description('Optional. Description of the credential.') - description: string? -}[] diff --git a/avm/res/automation/automation-account/credential/main.json b/avm/res/automation/automation-account/credential/main.json index a805bd02fe..03833e7c53 100644 --- a/avm/res/automation/automation-account/credential/main.json +++ b/avm/res/automation/automation-account/credential/main.json @@ -5,51 +5,13 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10580987489047715400" + "version": "0.30.23.60470", + "templateHash": "12611107514388164926" }, "name": "Automation Account Credential", "description": "This module deploys Azure Automation Account Credential.", "owner": "Azure/module-maintainers" }, - "definitions": { - "credentialType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. Name of the Automation Account credential." - } - }, - "userName": { - "type": "string", - "metadata": { - "description": "Required. The user name associated to the credential." - } - }, - "password": { - "type": "securestring", - "metadata": { - "description": "Required. Password of the credential." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Description of the credential." - } - } - } - }, - "metadata": { - "__bicep_export!": true - } - } - }, "parameters": { "automationAccountName": { "type": "string", @@ -57,10 +19,29 @@ "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." } }, - "credentials": { - "$ref": "#/definitions/credentialType", + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account credential." + } + }, + "userName": { + "type": "string", "metadata": { - "description": "Required. The credential definition." + "description": "Required. The user name associated to the credential." + } + }, + "password": { + "type": "securestring", + "metadata": { + "description": "Required. Password of the credential." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the credential." } } }, @@ -71,18 +52,14 @@ "apiVersion": "2022-08-08", "name": "[parameters('automationAccountName')]" }, - "automationAccount_credential": { - "copy": { - "name": "automationAccount_credential", - "count": "[length(parameters('credentials'))]" - }, + "credential": { "type": "Microsoft.Automation/automationAccounts/credentials", "apiVersion": "2023-11-01", - "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('credentials')[copyIndex()].name)]", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", "properties": { - "password": "[parameters('credentials')[copyIndex()].password]", - "userName": "[parameters('credentials')[copyIndex()].userName]", - "description": "[coalesce(tryGet(parameters('credentials')[copyIndex()], 'description'), '')]" + "password": "[parameters('password')]", + "userName": "[parameters('userName')]", + "description": "[coalesce(parameters('description'), '')]" }, "dependsOn": [ "automationAccount" @@ -91,24 +68,18 @@ }, "outputs": { "resourceId": { - "type": "array", + "type": "string", "metadata": { - "description": "The resource IDs of the credentials associated to the automation account." + "description": "The resource Id of the credential associated to the automation account." }, - "copy": { - "count": "[length(range(0, length(parameters('credentials'))))]", - "input": "[resourceId('Microsoft.Automation/automationAccounts/credentials', parameters('automationAccountName'), parameters('credentials')[range(0, length(parameters('credentials')))[copyIndex()]].name)]" - } + "value": "[resourceId('Microsoft.Automation/automationAccounts/credentials', parameters('automationAccountName'), parameters('name'))]" }, "name": { - "type": "array", + "type": "string", "metadata": { - "description": "The names of the credentials associated to the automation account." + "description": "The name of the credential associated to the automation account." }, - "copy": { - "count": "[length(range(0, length(parameters('credentials'))))]", - "input": "[parameters('credentials')[range(0, length(parameters('credentials')))[copyIndex()]].name]" - } + "value": "[parameters('name')]" }, "resourceGroupName": { "type": "string", diff --git a/avm/res/automation/automation-account/job-schedule/main.json b/avm/res/automation/automation-account/job-schedule/main.json index 0b9b9b697e..7fe15e27f2 100644 --- a/avm/res/automation/automation-account/job-schedule/main.json +++ b/avm/res/automation/automation-account/job-schedule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10826746631810286901" + "version": "0.30.23.60470", + "templateHash": "4313990302593445827" }, "name": "Automation Account Job Schedules", "description": "This module deploys an Azure Automation Account Job Schedule.", diff --git a/avm/res/automation/automation-account/main.bicep b/avm/res/automation/automation-account/main.bicep index 2bba584492..cc0a1569af 100644 --- a/avm/res/automation/automation-account/main.bicep +++ b/avm/res/automation/automation-account/main.bicep @@ -15,12 +15,12 @@ param location string = resourceGroup().location ]) param skuName string = 'Basic' +import { customerManagedKeyType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The customer managed key definition.') -param customerManagedKey customerManagedKeyType +param customerManagedKey customerManagedKeyType? -import { credentialType } from 'credential/main.bicep' @description('Optional. List of credentials to be created in the automation account.') -param credentials credentialType = [] +param credentials credentialType[]? @description('Optional. List of modules to be created in the automation account.') param modules array = [] @@ -41,7 +41,7 @@ param variables array = [] param linkedWorkspaceResourceId string = '' @description('Optional. List of gallerySolutions to be created in the linked log analytics workspace.') -param gallerySolutions array = [] +param gallerySolutions gallerySolutionType[]? @description('Optional. List of softwareUpdateConfigurations to be created in the automation account.') param softwareUpdateConfigurations array = [] @@ -57,20 +57,25 @@ param publicNetworkAccess string = '' @description('Optional. Disable local authentication profile used within the resource.') param disableLocalAuth bool = true +import { privateEndpointMultiServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointMultiServiceType[]? +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityAllType? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the Automation Account resource.') param tags object? @@ -206,13 +211,18 @@ resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' } } -module automationAccount_credentials 'credential/main.bicep' = if (!empty(credentials)) { - name: '${uniqueString(deployment().name, location)}-AutomationAccount-Credentials' - params: { - automationAccountName: automationAccount.name - credentials: credentials +module automationAccount_credentials 'credential/main.bicep' = [ + for (credential, index) in (credentials ?? []): { + name: '${uniqueString(deployment().name, location)}-AutomationAccount-Credential-${index}' + params: { + automationAccountName: automationAccount.name + name: credential.name + password: credential.password + userName: credential.userName + description: credential.?description + } } -} +] module automationAccount_modules 'module/main.bicep' = [ for (module, index) in modules: { @@ -234,13 +244,13 @@ module automationAccount_schedules 'schedule/main.bicep' = [ params: { name: schedule.name automationAccountName: automationAccount.name - advancedSchedule: contains(schedule, 'advancedSchedule') ? schedule.advancedSchedule : null - description: 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 : '' + advancedSchedule: schedule.?advancedSchedule + description: schedule.?description + expiryTime: schedule.?expiryTime + frequency: schedule.?frequency + interval: schedule.?interval + startTime: schedule.?startTime + timeZone: schedule.?timeZone } } ] @@ -252,9 +262,9 @@ module automationAccount_runbooks 'runbook/main.bicep' = [ name: runbook.name automationAccountName: automationAccount.name type: runbook.type - description: contains(runbook, 'description') ? runbook.description : '' - uri: contains(runbook, 'uri') ? runbook.uri : '' - version: contains(runbook, 'version') ? runbook.version : '' + description: runbook.?description + uri: runbook.?uri + version: runbook.?version sasTokenValidityLength: runbook.?sasTokenValidityLength scriptStorageAccountResourceId: runbook.?scriptStorageAccountResourceId location: location @@ -270,8 +280,8 @@ module automationAccount_jobSchedules 'job-schedule/main.bicep' = [ automationAccountName: automationAccount.name runbookName: jobSchedule.runbookName scheduleName: jobSchedule.scheduleName - parameters: contains(jobSchedule, 'parameters') ? jobSchedule.parameters : {} - runOn: contains(jobSchedule, 'runOn') ? jobSchedule.runOn : '' + parameters: jobSchedule.?parameters + runOn: jobSchedule.?runOn } dependsOn: [ automationAccount_schedules @@ -286,9 +296,9 @@ module automationAccount_variables 'variable/main.bicep' = [ params: { automationAccountName: automationAccount.name name: variable.name - description: contains(variable, 'description') ? variable.description : '' + description: variable.?description value: variable.value - isEncrypted: contains(variable, 'isEncrypted') ? variable.isEncrypted : true + isEncrypted: variable.?isEncrypted } } ] @@ -313,15 +323,14 @@ module automationAccount_linkedService 'modules/linked-service.bicep' = if (!emp ) } -module automationAccount_solutions 'br/public:avm/res/operations-management/solution:0.1.0' = [ - for (gallerySolution, index) in gallerySolutions: if (!empty(linkedWorkspaceResourceId)) { +module automationAccount_solutions 'br/public:avm/res/operations-management/solution:0.3.0' = [ + for (gallerySolution, index) in gallerySolutions ?? []: if (!empty(linkedWorkspaceResourceId)) { name: '${uniqueString(deployment().name, location)}-AutoAccount-Solution-${index}' params: { name: gallerySolution.name location: location logAnalyticsWorkspaceName: last(split(linkedWorkspaceResourceId, '/'))! - product: contains(gallerySolution, 'product') ? gallerySolution.product : 'OMSGallery' - publisher: contains(gallerySolution, 'publisher') ? gallerySolution.publisher : 'Microsoft' + plan: gallerySolution.plan enableTelemetry: enableTelemetry } // This is to support solution to law in different subscription and resource group than the automation account. @@ -349,74 +358,33 @@ module automationAccount_softwareUpdateConfigurations 'software-update-configura 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 : [] + azureVirtualMachines: softwareUpdateConfiguration.?azureVirtualMachines + excludeUpdates: softwareUpdateConfiguration.?excludeUpdates + expiryTime: softwareUpdateConfiguration.?expiryTime + expiryTimeOffsetMinutes: softwareUpdateConfiguration.?expiryTimeOffsetMinute + includeUpdates: softwareUpdateConfiguration.?includeUpdates + interval: softwareUpdateConfiguration.?interval + isEnabled: softwareUpdateConfiguration.?isEnabled + maintenanceWindow: softwareUpdateConfiguration.?maintenanceWindow + monthDays: softwareUpdateConfiguration.?monthDays + monthlyOccurrences: softwareUpdateConfiguration.?monthlyOccurrences + nextRun: softwareUpdateConfiguration.?nextRun + nextRunOffsetMinutes: softwareUpdateConfiguration.?nextRunOffsetMinutes + nonAzureComputerNames: softwareUpdateConfiguration.?nonAzureComputerNames + nonAzureQueries: softwareUpdateConfiguration.?nonAzureQueries + postTaskParameters: softwareUpdateConfiguration.?postTaskParameters + postTaskSource: softwareUpdateConfiguration.?postTaskSource + preTaskParameters: softwareUpdateConfiguration.?preTaskParameters + preTaskSource: softwareUpdateConfiguration.?preTaskSource + scheduleDescription: softwareUpdateConfiguration.?scheduleDescription + scopeByLocations: softwareUpdateConfiguration.?scopeByLocations + scopeByResources: softwareUpdateConfiguration.?scopeByResources + scopeByTags: softwareUpdateConfiguration.?scopeByTags + scopeByTagsOperation: softwareUpdateConfiguration.?scopeByTagsOperation + startTime: softwareUpdateConfiguration.?startTime + timeZone: softwareUpdateConfiguration.?timeZone + updateClassifications: softwareUpdateConfiguration.?updateClassifications + weekDays: softwareUpdateConfiguration.?weekDays } dependsOn: [ automationAccount_solutions @@ -566,189 +534,32 @@ output privateEndpoints array = [ // Definitions // // =============== // -type managedIdentitiesType = { - @description('Optional. Enables system assigned managed identity on the resource.') - systemAssigned: bool? - - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[]? -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? +@export() +type credentialType = { + @sys.description('Required. Name of the Automation Account credential.') + name: string -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? + @sys.description('Required. The user name associated to the credential.') + userName: string - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string + @sys.description('Required. Password of the credential.') + @secure() + password: string - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') + @sys.description('Optional. Description of the credential.') description: string? +} - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Required. The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file".') - service: string - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? - - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? - - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? - - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? - -type customerManagedKeyType = { - @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') - keyVaultResourceId: string - - @description('Required. The name of the customer managed key to use for encryption.') - keyName: string +import { solutionPlanType } from 'br/public:avm/res/operations-management/solution:0.3.0' - @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') - keyVersion: string? +@export() +type gallerySolutionType = { + @description('''Required. Name of the solution. + For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`. + For solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`. + The solution type is case-sensitive.''') + name: string - @description('Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use.') - userAssignedIdentityResourceId: string? -}? + @description('Required. Plan for solution object supported by the OperationsManagement resource provider.') + plan: solutionPlanType +} diff --git a/avm/res/automation/automation-account/main.json b/avm/res/automation/automation-account/main.json index e316b77c78..648ea43ae5 100644 --- a/avm/res/automation/automation-account/main.json +++ b/avm/res/automation/automation-account/main.json @@ -5,541 +5,636 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4084557661858315692" + "version": "0.30.23.60470", + "templateHash": "5140090215914688680" }, "name": "Automation Accounts", "description": "This module deploys an Azure Automation Account.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { + "credentialType": { "type": "object", "properties": { - "systemAssigned": { - "type": "bool", - "nullable": true, + "name": { + "type": "string", "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." + "description": "Required. Name of the Automation Account credential." } }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, + "userName": { + "type": "string", + "metadata": { + "description": "Required. The user name associated to the credential." + } + }, + "password": { + "type": "securestring", + "metadata": { + "description": "Required. Password of the credential." + } + }, + "description": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. Description of the credential." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "lockType": { + "gallerySolutionType": { "type": "object", "properties": { "name": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Required. Name of the solution.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.\nThe solution type is case-sensitive." } }, - "kind": { + "plan": { + "$ref": "#/definitions/solutionPlanType", + "metadata": { + "description": "Required. Plan for solution object supported by the OperationsManagement resource provider." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "_1.privateEndpointCustomDnsConfigType": { + "type": "object", + "properties": { + "fqdn": { "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "metadata": { - "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." - } - }, - "privateDnsZoneGroup": { + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." + "description": "Optional. The name of the private DNS Zone Group config." } }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, + "privateDnsZoneResourceId": { + "type": "string", "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + "description": "Required. The resource id of the private DNS zone." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." } }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a customer-managed key.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } } }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." } }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } - }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "privateEndpointMultiServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "metadata": { + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\" for a Storage Account's Private Endpoints." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can NOT be assumed (i.e., for services that have more than one subresource, like Storage Account with Blob (blob, table, queue, file, ...).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "customerManagedKeyType": { + "roleAssignmentType": { "type": "object", "properties": { - "keyVaultResourceId": { + "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "keyName": { + "roleDefinitionIdOrName": { "type": "string", "metadata": { - "description": "Required. The name of the customer managed key to use for encryption." + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, - "keyVersion": { + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + "description": "Optional. The description of the role assignment." } }, - "userAssignedIdentityResourceId": { + "condition": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true - }, - "credentialType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. Name of the Automation Account credential." - } - }, - "userName": { - "type": "string", - "metadata": { - "description": "Required. The user name associated to the credential." - } - }, - "password": { - "type": "securestring", - "metadata": { - "description": "Required. Password of the credential." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Description of the credential." - } + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "solutionPlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the solution to be created.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, it can be anything.\nThe solution type is case-sensitive.\nIf not provided, the value of the `name` parameter will be used." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product name of the deployed solution.\nFor Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.\nFor a third party solution, it can be anything.\nThis is case sensitive." + } + }, + "publisher": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value." } } }, "metadata": { "__bicep_imported_from!": { - "sourceTemplate": "credential/main.bicep" + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/res/operations-management/solution:0.3.0" } } } @@ -571,13 +666,17 @@ }, "customerManagedKey": { "$ref": "#/definitions/customerManagedKeyType", + "nullable": true, "metadata": { "description": "Optional. The customer managed key definition." } }, "credentials": { - "$ref": "#/definitions/credentialType", - "defaultValue": [], + "type": "array", + "items": { + "$ref": "#/definitions/credentialType" + }, + "nullable": true, "metadata": { "description": "Optional. List of credentials to be created in the automation account." } @@ -626,7 +725,10 @@ }, "gallerySolutions": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/gallerySolutionType" + }, + "nullable": true, "metadata": { "description": "Optional. List of gallerySolutions to be created in the linked log analytics workspace." } @@ -658,31 +760,45 @@ } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointMultiServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -873,10 +989,13 @@ ] }, "automationAccount_credentials": { - "condition": "[not(empty(parameters('credentials')))]", + "copy": { + "name": "automationAccount_credentials", + "count": "[length(coalesce(parameters('credentials'), createArray()))]" + }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-AutomationAccount-Credentials', uniqueString(deployment().name, parameters('location')))]", + "name": "[format('{0}-AutomationAccount-Credential-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "properties": { "expressionEvaluationOptions": { "scope": "inner" @@ -886,8 +1005,17 @@ "automationAccountName": { "value": "[parameters('name')]" }, - "credentials": { - "value": "[parameters('credentials')]" + "name": { + "value": "[coalesce(parameters('credentials'), createArray())[copyIndex()].name]" + }, + "password": { + "value": "[coalesce(parameters('credentials'), createArray())[copyIndex()].password]" + }, + "userName": { + "value": "[coalesce(parameters('credentials'), createArray())[copyIndex()].userName]" + }, + "description": { + "value": "[tryGet(coalesce(parameters('credentials'), createArray())[copyIndex()], 'description')]" } }, "template": { @@ -897,51 +1025,13 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10580987489047715400" + "version": "0.30.23.60470", + "templateHash": "12611107514388164926" }, "name": "Automation Account Credential", "description": "This module deploys Azure Automation Account Credential.", "owner": "Azure/module-maintainers" }, - "definitions": { - "credentialType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. Name of the Automation Account credential." - } - }, - "userName": { - "type": "string", - "metadata": { - "description": "Required. The user name associated to the credential." - } - }, - "password": { - "type": "securestring", - "metadata": { - "description": "Required. Password of the credential." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Description of the credential." - } - } - } - }, - "metadata": { - "__bicep_export!": true - } - } - }, "parameters": { "automationAccountName": { "type": "string", @@ -949,10 +1039,29 @@ "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." } }, - "credentials": { - "$ref": "#/definitions/credentialType", + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account credential." + } + }, + "userName": { + "type": "string", + "metadata": { + "description": "Required. The user name associated to the credential." + } + }, + "password": { + "type": "securestring", + "metadata": { + "description": "Required. Password of the credential." + } + }, + "description": { + "type": "string", + "nullable": true, "metadata": { - "description": "Required. The credential definition." + "description": "Optional. Description of the credential." } } }, @@ -963,18 +1072,14 @@ "apiVersion": "2022-08-08", "name": "[parameters('automationAccountName')]" }, - "automationAccount_credential": { - "copy": { - "name": "automationAccount_credential", - "count": "[length(parameters('credentials'))]" - }, + "credential": { "type": "Microsoft.Automation/automationAccounts/credentials", "apiVersion": "2023-11-01", - "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('credentials')[copyIndex()].name)]", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", "properties": { - "password": "[parameters('credentials')[copyIndex()].password]", - "userName": "[parameters('credentials')[copyIndex()].userName]", - "description": "[coalesce(tryGet(parameters('credentials')[copyIndex()], 'description'), '')]" + "password": "[parameters('password')]", + "userName": "[parameters('userName')]", + "description": "[coalesce(parameters('description'), '')]" }, "dependsOn": [ "automationAccount" @@ -983,24 +1088,18 @@ }, "outputs": { "resourceId": { - "type": "array", + "type": "string", "metadata": { - "description": "The resource IDs of the credentials associated to the automation account." + "description": "The resource Id of the credential associated to the automation account." }, - "copy": { - "count": "[length(range(0, length(parameters('credentials'))))]", - "input": "[resourceId('Microsoft.Automation/automationAccounts/credentials', parameters('automationAccountName'), parameters('credentials')[range(0, length(parameters('credentials')))[copyIndex()]].name)]" - } + "value": "[resourceId('Microsoft.Automation/automationAccounts/credentials', parameters('automationAccountName'), parameters('name'))]" }, "name": { - "type": "array", + "type": "string", "metadata": { - "description": "The names of the credentials associated to the automation account." + "description": "The name of the credential associated to the automation account." }, - "copy": { - "count": "[length(range(0, length(parameters('credentials'))))]", - "input": "[parameters('credentials')[range(0, length(parameters('credentials')))[copyIndex()]].name]" - } + "value": "[parameters('name')]" }, "resourceGroupName": { "type": "string", @@ -1056,8 +1155,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "14556422655915492083" + "version": "0.30.23.60470", + "templateHash": "15453846545391026191" }, "name": "Automation Account Modules", "description": "This module deploys an Azure Automation Account Module.", @@ -1184,13 +1283,27 @@ "automationAccountName": { "value": "[parameters('name')]" }, - "advancedSchedule": "[if(contains(parameters('schedules')[copyIndex()], 'advancedSchedule'), createObject('value', parameters('schedules')[copyIndex()].advancedSchedule), createObject('value', null()))]", - "description": "[if(contains(parameters('schedules')[copyIndex()], 'description'), createObject('value', parameters('schedules')[copyIndex()].description), createObject('value', ''))]", - "expiryTime": "[if(contains(parameters('schedules')[copyIndex()], 'expiryTime'), createObject('value', parameters('schedules')[copyIndex()].expiryTime), createObject('value', ''))]", - "frequency": "[if(contains(parameters('schedules')[copyIndex()], 'frequency'), createObject('value', parameters('schedules')[copyIndex()].frequency), createObject('value', 'OneTime'))]", - "interval": "[if(contains(parameters('schedules')[copyIndex()], 'interval'), createObject('value', parameters('schedules')[copyIndex()].interval), createObject('value', 0))]", - "startTime": "[if(contains(parameters('schedules')[copyIndex()], 'startTime'), createObject('value', parameters('schedules')[copyIndex()].startTime), createObject('value', ''))]", - "timeZone": "[if(contains(parameters('schedules')[copyIndex()], 'timeZone'), createObject('value', parameters('schedules')[copyIndex()].timeZone), createObject('value', ''))]" + "advancedSchedule": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'advancedSchedule')]" + }, + "description": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'description')]" + }, + "expiryTime": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'expiryTime')]" + }, + "frequency": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'frequency')]" + }, + "interval": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'interval')]" + }, + "startTime": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'startTime')]" + }, + "timeZone": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'timeZone')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -1198,8 +1311,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6299933839999486418" + "version": "0.30.23.60470", + "templateHash": "18156490457024191308" }, "name": "Automation Account Schedules", "description": "This module deploys an Azure Automation Account Schedule.", @@ -1354,9 +1467,15 @@ "type": { "value": "[parameters('runbooks')[copyIndex()].type]" }, - "description": "[if(contains(parameters('runbooks')[copyIndex()], 'description'), createObject('value', parameters('runbooks')[copyIndex()].description), createObject('value', ''))]", - "uri": "[if(contains(parameters('runbooks')[copyIndex()], 'uri'), createObject('value', parameters('runbooks')[copyIndex()].uri), createObject('value', ''))]", - "version": "[if(contains(parameters('runbooks')[copyIndex()], 'version'), createObject('value', parameters('runbooks')[copyIndex()].version), createObject('value', ''))]", + "description": { + "value": "[tryGet(parameters('runbooks')[copyIndex()], 'description')]" + }, + "uri": { + "value": "[tryGet(parameters('runbooks')[copyIndex()], 'uri')]" + }, + "version": { + "value": "[tryGet(parameters('runbooks')[copyIndex()], 'version')]" + }, "sasTokenValidityLength": { "value": "[tryGet(parameters('runbooks')[copyIndex()], 'sasTokenValidityLength')]" }, @@ -1377,8 +1496,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11653746330709835761" + "version": "0.30.23.60470", + "templateHash": "12957326312361613170" }, "name": "Automation Account Runbooks", "description": "This module deploys an Azure Automation Account Runbook.", @@ -1572,8 +1691,12 @@ "scheduleName": { "value": "[parameters('jobSchedules')[copyIndex()].scheduleName]" }, - "parameters": "[if(contains(parameters('jobSchedules')[copyIndex()], 'parameters'), createObject('value', parameters('jobSchedules')[copyIndex()].parameters), createObject('value', createObject()))]", - "runOn": "[if(contains(parameters('jobSchedules')[copyIndex()], 'runOn'), createObject('value', parameters('jobSchedules')[copyIndex()].runOn), createObject('value', ''))]" + "parameters": { + "value": "[tryGet(parameters('jobSchedules')[copyIndex()], 'parameters')]" + }, + "runOn": { + "value": "[tryGet(parameters('jobSchedules')[copyIndex()], 'runOn')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -1581,8 +1704,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10826746631810286901" + "version": "0.30.23.60470", + "templateHash": "4313990302593445827" }, "name": "Automation Account Job Schedules", "description": "This module deploys an Azure Automation Account Job Schedule.", @@ -1697,11 +1820,15 @@ "name": { "value": "[parameters('variables')[copyIndex()].name]" }, - "description": "[if(contains(parameters('variables')[copyIndex()], 'description'), createObject('value', parameters('variables')[copyIndex()].description), createObject('value', ''))]", + "description": { + "value": "[tryGet(parameters('variables')[copyIndex()], 'description')]" + }, "value": { "value": "[parameters('variables')[copyIndex()].value]" }, - "isEncrypted": "[if(contains(parameters('variables')[copyIndex()], 'isEncrypted'), createObject('value', parameters('variables')[copyIndex()].isEncrypted), createObject('value', true()))]" + "isEncrypted": { + "value": "[tryGet(parameters('variables')[copyIndex()], 'isEncrypted')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -1709,8 +1836,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13284693609482301780" + "version": "0.30.23.60470", + "templateHash": "11786120333296513300" }, "name": "Automation Account Variables", "description": "This module deploys an Azure Automation Account Variable.", @@ -1824,8 +1951,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12032441371027552374" + "version": "0.30.23.60470", + "templateHash": "9587193864623256690" }, "name": "Log Analytics Workspace Linked Services", "description": "This module deploys a Log Analytics Workspace Linked Service.", @@ -1919,7 +2046,7 @@ "automationAccount_solutions": { "copy": { "name": "automationAccount_solutions", - "count": "[length(parameters('gallerySolutions'))]" + "count": "[length(coalesce(parameters('gallerySolutions'), createArray()))]" }, "condition": "[not(empty(parameters('linkedWorkspaceResourceId')))]", "type": "Microsoft.Resources/deployments", @@ -1934,7 +2061,7 @@ "mode": "Incremental", "parameters": { "name": { - "value": "[parameters('gallerySolutions')[copyIndex()].name]" + "value": "[coalesce(parameters('gallerySolutions'), createArray())[copyIndex()].name]" }, "location": { "value": "[parameters('location')]" @@ -1942,30 +2069,68 @@ "logAnalyticsWorkspaceName": { "value": "[last(split(parameters('linkedWorkspaceResourceId'), '/'))]" }, - "product": "[if(contains(parameters('gallerySolutions')[copyIndex()], 'product'), createObject('value', parameters('gallerySolutions')[copyIndex()].product), createObject('value', 'OMSGallery'))]", - "publisher": "[if(contains(parameters('gallerySolutions')[copyIndex()], 'publisher'), createObject('value', parameters('gallerySolutions')[copyIndex()].publisher), createObject('value', 'Microsoft'))]", + "plan": { + "value": "[coalesce(parameters('gallerySolutions'), createArray())[copyIndex()].plan]" + }, "enableTelemetry": { "value": "[parameters('enableTelemetry')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18444780972506374592" + "version": "0.30.23.60470", + "templateHash": "1867653058254938383" }, "name": "Operations Management Solutions", "description": "This module deploys an Operations Management Solution.", "owner": "Azure/module-maintainers" }, + "definitions": { + "solutionPlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the solution to be created.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, it can be anything.\nThe solution type is case-sensitive.\nIf not provided, the value of the `name` parameter will be used." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product name of the deployed solution.\nFor Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.\nFor a third party solution, it can be anything.\nThis is case sensitive." + } + }, + "publisher": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", "metadata": { - "description": "Required. Name of the solution. For Microsoft published gallery solution the target solution resource name will be composed as `{name}({logAnalyticsWorkspaceName})`." + "description": "Required. Name of the solution.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.\nThe solution type is case-sensitive." + } + }, + "plan": { + "$ref": "#/definitions/solutionPlanType", + "metadata": { + "description": "Required. Plan for solution object supported by the OperationsManagement resource provider." } }, "logAnalyticsWorkspaceName": { @@ -1981,20 +2146,6 @@ "description": "Optional. Location for all resources." } }, - "product": { - "type": "string", - "defaultValue": "OMSGallery", - "metadata": { - "description": "Optional. The product of the deployed solution. For Microsoft published gallery solution it should be `OMSGallery` and the target solution resource product will be composed as `OMSGallery/{name}`. For third party solution, it can be anything. This is case sensitive." - } - }, - "publisher": { - "type": "string", - "defaultValue": "Microsoft", - "metadata": { - "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`." - } - }, "enableTelemetry": { "type": "bool", "defaultValue": true, @@ -2003,16 +2154,12 @@ } } }, - "variables": { - "solutionName": "[if(equals(parameters('publisher'), 'Microsoft'), format('{0}({1})', parameters('name'), parameters('logAnalyticsWorkspaceName')), parameters('name'))]", - "solutionProduct": "[if(equals(parameters('publisher'), 'Microsoft'), format('OMSGallery/{0}', parameters('name')), parameters('product'))]" - }, - "resources": [ - { + "resources": { + "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.operationsmanagement-solution.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.operationsmanagement-solution.{0}.{1}', replace('0.3.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -2028,36 +2175,45 @@ } } }, - { + "logAnalyticsWorkspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2021-06-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "solution": { "type": "Microsoft.OperationsManagement/solutions", "apiVersion": "2015-11-01-preview", - "name": "[variables('solutionName')]", + "name": "[parameters('name')]", "location": "[parameters('location')]", "properties": { "workspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]" }, "plan": { - "name": "[variables('solutionName')]", + "name": "[coalesce(tryGet(parameters('plan'), 'name'), parameters('name'))]", "promotionCode": "", - "product": "[variables('solutionProduct')]", - "publisher": "[parameters('publisher')]" - } + "product": "[parameters('plan').product]", + "publisher": "[coalesce(tryGet(parameters('plan'), 'publisher'), 'Microsoft')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] } - ], + }, "outputs": { "name": { "type": "string", "metadata": { "description": "The name of the deployed solution." }, - "value": "[variables('solutionName')]" + "value": "[parameters('name')]" }, "resourceId": { "type": "string", "metadata": { "description": "The resource ID of the deployed solution." }, - "value": "[resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName'))]" + "value": "[resourceId('Microsoft.OperationsManagement/solutions', parameters('name'))]" }, "resourceGroupName": { "type": "string", @@ -2071,7 +2227,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName')), '2015-11-01-preview', 'full').location]" + "value": "[reference('solution', '2015-11-01-preview', 'full').location]" } } } @@ -2109,42 +2265,97 @@ "rebootSetting": { "value": "[parameters('softwareUpdateConfigurations')[copyIndex()].rebootSetting]" }, - "azureVirtualMachines": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'azureVirtualMachines'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].azureVirtualMachines), createObject('value', createArray()))]", - "excludeUpdates": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'excludeUpdates'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].excludeUpdates), createObject('value', createArray()))]", - "expiryTime": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTime'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].expiryTime), createObject('value', ''))]", - "expiryTimeOffsetMinutes": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTimeOffsetMinutes'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].expiryTimeOffsetMinute), createObject('value', 0))]", - "includeUpdates": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'includeUpdates'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].includeUpdates), createObject('value', createArray()))]", - "interval": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'interval'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].interval), createObject('value', 1))]", - "isEnabled": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'isEnabled'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].isEnabled), createObject('value', true()))]", - "maintenanceWindow": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'maintenanceWindow'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].maintenanceWindow), createObject('value', 'PT2H'))]", - "monthDays": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthDays'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].monthDays), createObject('value', createArray()))]", - "monthlyOccurrences": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthlyOccurrences'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].monthlyOccurrences), createObject('value', createArray()))]", - "nextRun": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRun'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nextRun), createObject('value', ''))]", - "nextRunOffsetMinutes": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRunOffsetMinutes'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nextRunOffsetMinutes), createObject('value', 0))]", - "nonAzureComputerNames": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureComputerNames'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nonAzureComputerNames), createObject('value', createArray()))]", - "nonAzureQueries": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureQueries'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nonAzureQueries), createObject('value', createArray()))]", - "postTaskParameters": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskParameters'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].postTaskParameters), createObject('value', createObject()))]", - "postTaskSource": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskSource'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].postTaskSource), createObject('value', ''))]", - "preTaskParameters": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskParameters'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].preTaskParameters), createObject('value', createObject()))]", - "preTaskSource": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskSource'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].preTaskSource), createObject('value', ''))]", - "scheduleDescription": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scheduleDescription'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scheduleDescription), createObject('value', ''))]", - "scopeByLocations": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByLocations'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByLocations), createObject('value', createArray()))]", - "scopeByResources": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByResources'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByResources), createObject('value', createArray(subscription().id)))]", - "scopeByTags": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTags'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByTags), createObject('value', createObject()))]", - "scopeByTagsOperation": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTagsOperation'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByTagsOperation), createObject('value', 'All'))]", - "startTime": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'startTime'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].startTime), createObject('value', ''))]", - "timeZone": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'timeZone'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].timeZone), createObject('value', 'UTC'))]", - "updateClassifications": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'updateClassifications'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].updateClassifications), createObject('value', createArray('Critical', 'Security')))]", - "weekDays": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'weekDays'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].weekDays), createObject('value', createArray()))]" + "azureVirtualMachines": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'azureVirtualMachines')]" + }, + "excludeUpdates": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'excludeUpdates')]" + }, + "expiryTime": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTime')]" + }, + "expiryTimeOffsetMinutes": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTimeOffsetMinute')]" + }, + "includeUpdates": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'includeUpdates')]" + }, + "interval": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'interval')]" + }, + "isEnabled": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'isEnabled')]" + }, + "maintenanceWindow": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'maintenanceWindow')]" + }, + "monthDays": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthDays')]" + }, + "monthlyOccurrences": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthlyOccurrences')]" + }, + "nextRun": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRun')]" + }, + "nextRunOffsetMinutes": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRunOffsetMinutes')]" + }, + "nonAzureComputerNames": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureComputerNames')]" + }, + "nonAzureQueries": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureQueries')]" + }, + "postTaskParameters": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskParameters')]" + }, + "postTaskSource": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskSource')]" + }, + "preTaskParameters": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskParameters')]" + }, + "preTaskSource": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskSource')]" + }, + "scheduleDescription": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scheduleDescription')]" + }, + "scopeByLocations": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByLocations')]" + }, + "scopeByResources": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByResources')]" + }, + "scopeByTags": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTags')]" + }, + "scopeByTagsOperation": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTagsOperation')]" + }, + "startTime": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'startTime')]" + }, + "timeZone": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'timeZone')]" + }, + "updateClassifications": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'updateClassifications')]" + }, + "weekDays": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'weekDays')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "752305553206238634" + "version": "0.30.23.60470", + "templateHash": "1633069486738674821" }, "name": "Automation Account Software Update Configurations", "description": "This module deploys an Azure Automation Account Software Update Configuration.", @@ -2276,28 +2487,28 @@ }, "preTaskParameters": { "type": "object", - "defaultValue": {}, + "nullable": true, "metadata": { "description": "Optional. Parameters provided to the task running before the deployment schedule." } }, "preTaskSource": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The source of the task running before the deployment schedule." } }, "postTaskParameters": { "type": "object", - "defaultValue": {}, + "nullable": true, "metadata": { "description": "Optional. Parameters provided to the task running after the deployment schedule." } }, "postTaskSource": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The source of the task running after the deployment schedule." } @@ -2347,7 +2558,10 @@ }, "weekDays": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "nullable": true, "allowedValues": [ "Monday", "Tuesday", @@ -2363,7 +2577,10 @@ }, "monthDays": { "type": "array", - "defaultValue": [], + "items": { + "type": "int" + }, + "nullable": true, "allowedValues": [ 1, 2, @@ -2403,7 +2620,7 @@ }, "monthlyOccurrences": { "type": "array", - "defaultValue": [], + "nullable": true, "metadata": { "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." } @@ -2461,8 +2678,14 @@ "variables": { "updateClassificationsVar": "[replace(replace(replace(replace(string(parameters('updateClassifications')), ',', ', '), '[', ''), ']', ''), '\"', '')]" }, - "resources": [ - { + "resources": { + "automationAccount": { + "existing": true, + "type": "Microsoft.Automation/automationAccounts", + "apiVersion": "2022-08-08", + "name": "[parameters('automationAccountName')]" + }, + "softwareUpdateConfiguration": { "type": "Microsoft.Automation/automationAccounts/softwareUpdateConfigurations", "apiVersion": "2019-06-01", "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", @@ -2490,12 +2713,12 @@ }, "tasks": { "preTask": { - "parameters": "[if(empty(parameters('preTaskParameters')), null(), parameters('preTaskParameters'))]", - "source": "[if(empty(parameters('preTaskSource')), null(), parameters('preTaskSource'))]" + "parameters": "[parameters('preTaskParameters')]", + "source": "[parameters('preTaskSource')]" }, "postTask": { - "parameters": "[if(empty(parameters('postTaskParameters')), null(), parameters('postTaskParameters'))]", - "source": "[if(empty(parameters('postTaskSource')), null(), parameters('postTaskSource'))]" + "parameters": "[parameters('postTaskParameters')]", + "source": "[parameters('postTaskSource')]" } }, "scheduleInfo": { @@ -2504,9 +2727,9 @@ "isEnabled": "[parameters('isEnabled')]", "timeZone": "[parameters('timeZone')]", "advancedSchedule": { - "weekDays": "[if(empty(parameters('weekDays')), null(), parameters('weekDays'))]", - "monthDays": "[if(empty(parameters('monthDays')), null(), parameters('monthDays'))]", - "monthlyOccurrences": "[if(empty(parameters('monthlyOccurrences')), null(), parameters('monthlyOccurrences'))]" + "weekDays": "[parameters('weekDays')]", + "monthDays": "[parameters('monthDays')]", + "monthlyOccurrences": "[parameters('monthlyOccurrences')]" }, "startTime": "[if(empty(parameters('startTime')), dateTimeAdd(parameters('baseTime'), 'PT10M'), parameters('startTime'))]", "expiryTime": "[parameters('expiryTime')]", @@ -2515,9 +2738,12 @@ "nextRunOffsetMinutes": "[parameters('nextRunOffsetMinutes')]", "description": "[parameters('scheduleDescription')]" } - } + }, + "dependsOn": [ + "automationAccount" + ] } - ], + }, "outputs": { "name": { "type": "string", diff --git a/avm/res/automation/automation-account/module/main.json b/avm/res/automation/automation-account/module/main.json index a84aab8636..ddb20a1f93 100644 --- a/avm/res/automation/automation-account/module/main.json +++ b/avm/res/automation/automation-account/module/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "14556422655915492083" + "version": "0.30.23.60470", + "templateHash": "15453846545391026191" }, "name": "Automation Account Modules", "description": "This module deploys an Azure Automation Account Module.", diff --git a/avm/res/automation/automation-account/runbook/main.json b/avm/res/automation/automation-account/runbook/main.json index 317cf0c2c5..158d2dffd6 100644 --- a/avm/res/automation/automation-account/runbook/main.json +++ b/avm/res/automation/automation-account/runbook/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11653746330709835761" + "version": "0.30.23.60470", + "templateHash": "12957326312361613170" }, "name": "Automation Account Runbooks", "description": "This module deploys an Azure Automation Account Runbook.", diff --git a/avm/res/automation/automation-account/schedule/main.json b/avm/res/automation/automation-account/schedule/main.json index 46c5820b48..82bfd83645 100644 --- a/avm/res/automation/automation-account/schedule/main.json +++ b/avm/res/automation/automation-account/schedule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6299933839999486418" + "version": "0.30.23.60470", + "templateHash": "18156490457024191308" }, "name": "Automation Account Schedules", "description": "This module deploys an Azure Automation Account Schedule.", diff --git a/avm/res/automation/automation-account/software-update-configuration/README.md b/avm/res/automation/automation-account/software-update-configuration/README.md index b0117c0376..45a7b8ca67 100644 --- a/avm/res/automation/automation-account/software-update-configuration/README.md +++ b/avm/res/automation/automation-account/software-update-configuration/README.md @@ -200,7 +200,6 @@ Can be used with frequency 'Month'. Provides the specific days of the month to r - Required: No - Type: array -- Default: `[]` - Allowed: ```Bicep [ @@ -244,7 +243,6 @@ Can be used with frequency 'Month'. Provides the pattern/cadence for running the - Required: No - Type: array -- Default: `[]` ### Parameter: `nextRun` @@ -284,7 +282,6 @@ Parameters provided to the task running after the deployment schedule. - Required: No - Type: object -- Default: `{}` ### Parameter: `postTaskSource` @@ -292,7 +289,6 @@ The source of the task running after the deployment schedule. - Required: No - Type: string -- Default: `''` ### Parameter: `preTaskParameters` @@ -300,7 +296,6 @@ Parameters provided to the task running before the deployment schedule. - Required: No - Type: object -- Default: `{}` ### Parameter: `preTaskSource` @@ -308,7 +303,6 @@ The source of the task running before the deployment schedule. - Required: No - Type: string -- Default: `''` ### Parameter: `scheduleDescription` @@ -412,7 +406,6 @@ Required when used with frequency 'Week'. Specified the day of the week to run t - Required: No - Type: array -- Default: `[]` - Allowed: ```Bicep [ diff --git a/avm/res/automation/automation-account/software-update-configuration/main.bicep b/avm/res/automation/automation-account/software-update-configuration/main.bicep index 2408a52a41..7a2ff63aa5 100644 --- a/avm/res/automation/automation-account/software-update-configuration/main.bicep +++ b/avm/res/automation/automation-account/software-update-configuration/main.bicep @@ -79,16 +79,16 @@ param scopeByTagsOperation string = 'All' param scopeByLocations array = [] @description('Optional. Parameters provided to the task running before the deployment schedule.') -param preTaskParameters object = {} +param preTaskParameters object? @description('Optional. The source of the task running before the deployment schedule.') -param preTaskSource string = '' +param preTaskSource string? @description('Optional. Parameters provided to the task running after the deployment schedule.') -param postTaskParameters object = {} +param postTaskParameters object? @description('Optional. The source of the task running after the deployment schedule.') -param postTaskSource string = '' +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) @@ -119,7 +119,7 @@ param nonAzureComputerNames array = [] 'Saturday' 'Sunday' ]) -param weekDays array = [] +param weekDays string[]? @description('Optional. Can be used with frequency \'Month\'. Provides the specific days of the month to run the deployment schedule.') @allowed([ @@ -155,10 +155,10 @@ param weekDays array = [] 30 31 ]) -param monthDays array = [] +param monthDays int[]? @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 = [] +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 = '' @@ -232,12 +232,12 @@ resource softwareUpdateConfiguration 'Microsoft.Automation/automationAccounts/so } tasks: { preTask: { - parameters: (empty(preTaskParameters) ? null : preTaskParameters) - source: (empty(preTaskSource) ? null : preTaskSource) + parameters: preTaskParameters + source: preTaskSource } postTask: { - parameters: (empty(postTaskParameters) ? null : postTaskParameters) - source: (empty(postTaskSource) ? null : postTaskSource) + parameters: postTaskParameters + source: postTaskSource } } scheduleInfo: { @@ -246,9 +246,9 @@ resource softwareUpdateConfiguration 'Microsoft.Automation/automationAccounts/so isEnabled: isEnabled timeZone: timeZone advancedSchedule: { - weekDays: (empty(weekDays) ? null : weekDays) - monthDays: (empty(monthDays) ? null : monthDays) - monthlyOccurrences: (empty(monthlyOccurrences) ? null : monthlyOccurrences) + weekDays: weekDays + monthDays: monthDays + monthlyOccurrences: monthlyOccurrences } startTime: (empty(startTime) ? dateTimeAdd(baseTime, 'PT10M') : startTime) expiryTime: expiryTime diff --git a/avm/res/automation/automation-account/software-update-configuration/main.json b/avm/res/automation/automation-account/software-update-configuration/main.json index 8f7f4c5ecb..a5ba1655ea 100644 --- a/avm/res/automation/automation-account/software-update-configuration/main.json +++ b/avm/res/automation/automation-account/software-update-configuration/main.json @@ -1,11 +1,12 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "752305553206238634" + "version": "0.30.23.60470", + "templateHash": "1633069486738674821" }, "name": "Automation Account Software Update Configurations", "description": "This module deploys an Azure Automation Account Software Update Configuration.", @@ -137,28 +138,28 @@ }, "preTaskParameters": { "type": "object", - "defaultValue": {}, + "nullable": true, "metadata": { "description": "Optional. Parameters provided to the task running before the deployment schedule." } }, "preTaskSource": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The source of the task running before the deployment schedule." } }, "postTaskParameters": { "type": "object", - "defaultValue": {}, + "nullable": true, "metadata": { "description": "Optional. Parameters provided to the task running after the deployment schedule." } }, "postTaskSource": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The source of the task running after the deployment schedule." } @@ -208,7 +209,10 @@ }, "weekDays": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "nullable": true, "allowedValues": [ "Monday", "Tuesday", @@ -224,7 +228,10 @@ }, "monthDays": { "type": "array", - "defaultValue": [], + "items": { + "type": "int" + }, + "nullable": true, "allowedValues": [ 1, 2, @@ -264,7 +271,7 @@ }, "monthlyOccurrences": { "type": "array", - "defaultValue": [], + "nullable": true, "metadata": { "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." } @@ -322,8 +329,14 @@ "variables": { "updateClassificationsVar": "[replace(replace(replace(replace(string(parameters('updateClassifications')), ',', ', '), '[', ''), ']', ''), '\"', '')]" }, - "resources": [ - { + "resources": { + "automationAccount": { + "existing": true, + "type": "Microsoft.Automation/automationAccounts", + "apiVersion": "2022-08-08", + "name": "[parameters('automationAccountName')]" + }, + "softwareUpdateConfiguration": { "type": "Microsoft.Automation/automationAccounts/softwareUpdateConfigurations", "apiVersion": "2019-06-01", "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", @@ -351,12 +364,12 @@ }, "tasks": { "preTask": { - "parameters": "[if(empty(parameters('preTaskParameters')), null(), parameters('preTaskParameters'))]", - "source": "[if(empty(parameters('preTaskSource')), null(), parameters('preTaskSource'))]" + "parameters": "[parameters('preTaskParameters')]", + "source": "[parameters('preTaskSource')]" }, "postTask": { - "parameters": "[if(empty(parameters('postTaskParameters')), null(), parameters('postTaskParameters'))]", - "source": "[if(empty(parameters('postTaskSource')), null(), parameters('postTaskSource'))]" + "parameters": "[parameters('postTaskParameters')]", + "source": "[parameters('postTaskSource')]" } }, "scheduleInfo": { @@ -365,9 +378,9 @@ "isEnabled": "[parameters('isEnabled')]", "timeZone": "[parameters('timeZone')]", "advancedSchedule": { - "weekDays": "[if(empty(parameters('weekDays')), null(), parameters('weekDays'))]", - "monthDays": "[if(empty(parameters('monthDays')), null(), parameters('monthDays'))]", - "monthlyOccurrences": "[if(empty(parameters('monthlyOccurrences')), null(), parameters('monthlyOccurrences'))]" + "weekDays": "[parameters('weekDays')]", + "monthDays": "[parameters('monthDays')]", + "monthlyOccurrences": "[parameters('monthlyOccurrences')]" }, "startTime": "[if(empty(parameters('startTime')), dateTimeAdd(parameters('baseTime'), 'PT10M'), parameters('startTime'))]", "expiryTime": "[parameters('expiryTime')]", @@ -376,9 +389,12 @@ "nextRunOffsetMinutes": "[parameters('nextRunOffsetMinutes')]", "description": "[parameters('scheduleDescription')]" } - } + }, + "dependsOn": [ + "automationAccount" + ] } - ], + }, "outputs": { "name": { "type": "string", diff --git a/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep index a3dfb495d2..afcdf60468 100644 --- a/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep +++ b/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep @@ -76,9 +76,11 @@ module testDeployment '../../../main.bicep' = [ ] gallerySolutions: [ { - name: 'Updates' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'Updates(${last(split(diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId, '/'))})' + plan: { + product: 'OMSGallery/Updates' + publisher: 'Microsoft' + } } ] jobSchedules: [ diff --git a/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep index 355d2a8e53..4ee50b8f61 100644 --- a/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep @@ -76,9 +76,10 @@ module testDeployment '../../../main.bicep' = [ ] gallerySolutions: [ { - name: 'Updates' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'Updates(${last(split(diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId, '/'))})' + plan: { + product: 'OMSGallery/Updates' + } } ] jobSchedules: [ diff --git a/avm/res/automation/automation-account/variable/main.json b/avm/res/automation/automation-account/variable/main.json index 70ba3c0c1e..8e3f316a7d 100644 --- a/avm/res/automation/automation-account/variable/main.json +++ b/avm/res/automation/automation-account/variable/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13284693609482301780" + "version": "0.30.23.60470", + "templateHash": "11786120333296513300" }, "name": "Automation Account Variables", "description": "This module deploys an Azure Automation Account Variable.", diff --git a/avm/res/automation/automation-account/version.json b/avm/res/automation/automation-account/version.json index 0f81d22abc..a830c3d961 100644 --- a/avm/res/automation/automation-account/version.json +++ b/avm/res/automation/automation-account/version.json @@ -1,7 +1,7 @@ { - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.8", - "pathFilters": [ - "./main.json" - ] + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.10", + "pathFilters": [ + "./main.json" + ] } \ No newline at end of file diff --git a/avm/res/batch/batch-account/README.md b/avm/res/batch/batch-account/README.md index 0cf0a66b37..1a6dcfffe6 100644 --- a/avm/res/batch/batch-account/README.md +++ b/avm/res/batch/batch-account/README.md @@ -1436,15 +1436,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1453,6 +1451,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/batch/batch-account/main.bicep b/avm/res/batch/batch-account/main.bicep index ab8e9a72eb..0bdc99ce3c 100644 --- a/avm/res/batch/batch-account/main.bicep +++ b/avm/res/batch/batch-account/main.bicep @@ -469,7 +469,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/batch/batch-account/main.json b/avm/res/batch/batch-account/main.json index 59bd76bfef..fa12259d09 100644 --- a/avm/res/batch/batch-account/main.json +++ b/avm/res/batch/batch-account/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10214588768781913112" + "version": "0.30.23.60470", + "templateHash": "9326027237179724855" }, "name": "Batch Accounts", "description": "This module deploys a Batch Account.", @@ -308,7 +308,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md index de250d1472..322627a7e1 100644 --- a/avm/res/cache/redis/README.md +++ b/avm/res/cache/redis/README.md @@ -1370,15 +1370,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1387,6 +1385,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep index 9e866bb89e..2eda0b9e71 100644 --- a/avm/res/cache/redis/main.bicep +++ b/avm/res/cache/redis/main.bicep @@ -421,7 +421,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/cache/redis/main.json b/avm/res/cache/redis/main.json index 222f86491e..24322d1c3b 100644 --- a/avm/res/cache/redis/main.json +++ b/avm/res/cache/redis/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8427702382536251551" + "version": "0.30.23.60470", + "templateHash": "4783503622444970338" }, "name": "Redis Cache", "description": "This module deploys a Redis Cache.", @@ -164,7 +164,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -1634,8 +1634,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6993324639761594928" + "version": "0.30.23.60470", + "templateHash": "10405637679168200939" }, "name": "Redis Cache Linked Servers", "description": "This module connects a primary and secondary Redis Cache together for geo-replication.", @@ -1809,4 +1809,4 @@ } } } -} +} \ No newline at end of file diff --git a/avm/res/cdn/profile/README.md b/avm/res/cdn/profile/README.md index cdbbe70b4d..1a43a43d99 100644 --- a/avm/res/cdn/profile/README.md +++ b/avm/res/cdn/profile/README.md @@ -1211,6 +1211,250 @@ Array of origin group objects. Required if the afdEndpoints is specified. - Type: array - Default: `[]` +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`loadBalancingSettings`](#parameter-origingroupsloadbalancingsettings) | object | Load balancing settings for a backend pool. | +| [`name`](#parameter-origingroupsname) | string | The name of the origin group. | +| [`origins`](#parameter-origingroupsorigins) | array | The list of origins within the origin group. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`healthProbeSettings`](#parameter-origingroupshealthprobesettings) | object | Health probe settings to the origin that is used to determine the health of the origin. | +| [`sessionAffinityState`](#parameter-origingroupssessionaffinitystate) | string | Whether to allow session affinity on this host. | +| [`trafficRestorationTimeToHealedOrNewEndpointsInMinutes`](#parameter-origingroupstrafficrestorationtimetohealedornewendpointsinminutes) | int | Time in minutes to shift the traffic to the endpoint gradually when an unhealthy endpoint comes healthy or a new endpoint is added. Default is 10 mins. | + +### Parameter: `originGroups.loadBalancingSettings` + +Load balancing settings for a backend pool. + +- Required: Yes +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`additionalLatencyInMilliseconds`](#parameter-origingroupsloadbalancingsettingsadditionallatencyinmilliseconds) | int | Additional latency in milliseconds for probes to the backend. Must be between 0 and 1000. | +| [`sampleSize`](#parameter-origingroupsloadbalancingsettingssamplesize) | int | Number of samples to consider for load balancing decisions. | +| [`successfulSamplesRequired`](#parameter-origingroupsloadbalancingsettingssuccessfulsamplesrequired) | int | Number of samples within the sample window that must be successful to mark the backend as healthy. | + +### Parameter: `originGroups.loadBalancingSettings.additionalLatencyInMilliseconds` + +Additional latency in milliseconds for probes to the backend. Must be between 0 and 1000. + +- Required: Yes +- Type: int + +### Parameter: `originGroups.loadBalancingSettings.sampleSize` + +Number of samples to consider for load balancing decisions. + +- Required: Yes +- Type: int + +### Parameter: `originGroups.loadBalancingSettings.successfulSamplesRequired` + +Number of samples within the sample window that must be successful to mark the backend as healthy. + +- Required: Yes +- Type: int + +### Parameter: `originGroups.name` + +The name of the origin group. + +- Required: Yes +- Type: string + +### Parameter: `originGroups.origins` + +The list of origins within the origin group. + +- Required: Yes +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`hostName`](#parameter-origingroupsoriginshostname) | string | The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint. | +| [`name`](#parameter-origingroupsoriginsname) | string | The name of the origion. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enabledState`](#parameter-origingroupsoriginsenabledstate) | string | Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool. | +| [`enforceCertificateNameCheck`](#parameter-origingroupsoriginsenforcecertificatenamecheck) | bool | Whether to enable certificate name check at origin level. | +| [`httpPort`](#parameter-origingroupsoriginshttpport) | int | The value of the HTTP port. Must be between 1 and 65535. | +| [`httpsPort`](#parameter-origingroupsoriginshttpsport) | int | The value of the HTTPS port. Must be between 1 and 65535. | +| [`originHostHeader`](#parameter-origingroupsoriginsoriginhostheader) | string | The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint. | +| [`priority`](#parameter-origingroupsoriginspriority) | int | Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5. | +| [`sharedPrivateLinkResource`](#parameter-origingroupsoriginssharedprivatelinkresource) | object | The properties of the private link resource for private origin. | +| [`weight`](#parameter-origingroupsoriginsweight) | int | Weight of the origin in given origin group for load balancing. Must be between 1 and 1000. | + +### Parameter: `originGroups.origins.hostName` + +The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint. + +- Required: Yes +- Type: string + +### Parameter: `originGroups.origins.name` + +The name of the origion. + +- Required: Yes +- Type: string + +### Parameter: `originGroups.origins.enabledState` + +Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `originGroups.origins.enforceCertificateNameCheck` + +Whether to enable certificate name check at origin level. + +- Required: No +- Type: bool + +### Parameter: `originGroups.origins.httpPort` + +The value of the HTTP port. Must be between 1 and 65535. + +- Required: No +- Type: int + +### Parameter: `originGroups.origins.httpsPort` + +The value of the HTTPS port. Must be between 1 and 65535. + +- Required: No +- Type: int + +### Parameter: `originGroups.origins.originHostHeader` + +The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint. + +- Required: No +- Type: string + +### Parameter: `originGroups.origins.priority` + +Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5. + +- Required: No +- Type: int + +### Parameter: `originGroups.origins.sharedPrivateLinkResource` + +The properties of the private link resource for private origin. + +- Required: No +- Type: object + +### Parameter: `originGroups.origins.weight` + +Weight of the origin in given origin group for load balancing. Must be between 1 and 1000. + +- Required: No +- Type: int + +### Parameter: `originGroups.healthProbeSettings` + +Health probe settings to the origin that is used to determine the health of the origin. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`probeIntervalInSeconds`](#parameter-origingroupshealthprobesettingsprobeintervalinseconds) | int | The number of seconds between health probes.Default is 240sec. | +| [`probePath`](#parameter-origingroupshealthprobesettingsprobepath) | string | The path relative to the origin that is used to determine the health of the origin. | +| [`probeProtocol`](#parameter-origingroupshealthprobesettingsprobeprotocol) | string | Protocol to use for health probe. | +| [`probeRequestType`](#parameter-origingroupshealthprobesettingsproberequesttype) | string | The request type to probe. | + +### Parameter: `originGroups.healthProbeSettings.probeIntervalInSeconds` + +The number of seconds between health probes.Default is 240sec. + +- Required: No +- Type: int + +### Parameter: `originGroups.healthProbeSettings.probePath` + +The path relative to the origin that is used to determine the health of the origin. + +- Required: No +- Type: string + +### Parameter: `originGroups.healthProbeSettings.probeProtocol` + +Protocol to use for health probe. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Http' + 'Https' + 'NotSet' + ] + ``` + +### Parameter: `originGroups.healthProbeSettings.probeRequestType` + +The request type to probe. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'GET' + 'HEAD' + 'NotSet' + ] + ``` + +### Parameter: `originGroups.sessionAffinityState` + +Whether to allow session affinity on this host. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `originGroups.trafficRestorationTimeToHealedOrNewEndpointsInMinutes` + +Time in minutes to shift the traffic to the endpoint gradually when an unhealthy endpoint comes healthy or a new endpoint is added. Default is 10 mins. + +- Required: No +- Type: int + ### Parameter: `afdEndpoints` Array of AFD endpoint objects. @@ -1219,6 +1463,271 @@ Array of AFD endpoint objects. - Type: array - Default: `[]` +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-afdendpointsname) | string | The name of the AFD Endpoint. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoGeneratedDomainNameLabelScope`](#parameter-afdendpointsautogenerateddomainnamelabelscope) | string | The scope of the auto-generated domain name label. | +| [`enabledState`](#parameter-afdendpointsenabledstate) | string | The state of the AFD Endpoint. | +| [`routes`](#parameter-afdendpointsroutes) | array | The list of routes for this AFD Endpoint. | +| [`tags`](#parameter-afdendpointstags) | object | The tags for the AFD Endpoint. | + +### Parameter: `afdEndpoints.name` + +The name of the AFD Endpoint. + +- Required: Yes +- Type: string + +### Parameter: `afdEndpoints.autoGeneratedDomainNameLabelScope` + +The scope of the auto-generated domain name label. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'NoReuse' + 'ResourceGroupReuse' + 'SubscriptionReuse' + 'TenantReuse' + ] + ``` + +### Parameter: `afdEndpoints.enabledState` + +The state of the AFD Endpoint. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `afdEndpoints.routes` + +The list of routes for this AFD Endpoint. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-afdendpointsroutesname) | string | The name of the route. | +| [`originGroupName`](#parameter-afdendpointsroutesorigingroupname) | string | The name of the origin group. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`cacheConfiguration`](#parameter-afdendpointsroutescacheconfiguration) | object | The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object. | +| [`customDomainNames`](#parameter-afdendpointsroutescustomdomainnames) | array | The names of the custom domains. | +| [`enabledState`](#parameter-afdendpointsroutesenabledstate) | string | Whether to enable use of this rule. | +| [`forwardingProtocol`](#parameter-afdendpointsroutesforwardingprotocol) | string | The protocol this rule will use when forwarding traffic to backends. | +| [`httpsRedirect`](#parameter-afdendpointsrouteshttpsredirect) | string | Whether to automatically redirect HTTP traffic to HTTPS traffic. | +| [`linkToDefaultDomain`](#parameter-afdendpointsrouteslinktodefaultdomain) | string | Whether this route will be linked to the default endpoint domain. | +| [`originPath`](#parameter-afdendpointsroutesoriginpath) | string | A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath. | +| [`patternsToMatch`](#parameter-afdendpointsroutespatternstomatch) | array | The route patterns of the rule. | +| [`ruleSets`](#parameter-afdendpointsroutesrulesets) | array | The rule sets of the rule. | +| [`supportedProtocols`](#parameter-afdendpointsroutessupportedprotocols) | array | The supported protocols of the rule. | + +### Parameter: `afdEndpoints.routes.name` + +The name of the route. + +- Required: Yes +- Type: string + +### Parameter: `afdEndpoints.routes.originGroupName` + +The name of the origin group. + +- Required: Yes +- Type: string + +### Parameter: `afdEndpoints.routes.cacheConfiguration` + +The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`compressionSettings`](#parameter-afdendpointsroutescacheconfigurationcompressionsettings) | object | Compression settings. | +| [`queryParameters`](#parameter-afdendpointsroutescacheconfigurationqueryparameters) | string | Query parameters to include or exclude (comma separated). | +| [`queryStringCachingBehavior`](#parameter-afdendpointsroutescacheconfigurationquerystringcachingbehavior) | string | Defines how Frontdoor caches requests that include query strings. | + +### Parameter: `afdEndpoints.routes.cacheConfiguration.compressionSettings` + +Compression settings. + +- Required: Yes +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`contentTypesToCompress`](#parameter-afdendpointsroutescacheconfigurationcompressionsettingscontenttypestocompress) | array | List of content types on which compression applies. The value should be a valid MIME type. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`iscontentTypeToCompressAll`](#parameter-afdendpointsroutescacheconfigurationcompressionsettingsiscontenttypetocompressall) | bool | Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB. | + +### Parameter: `afdEndpoints.routes.cacheConfiguration.compressionSettings.contentTypesToCompress` + +List of content types on which compression applies. The value should be a valid MIME type. + +- Required: Yes +- Type: array + +### Parameter: `afdEndpoints.routes.cacheConfiguration.compressionSettings.iscontentTypeToCompressAll` + +Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB. + +- Required: No +- Type: bool + +### Parameter: `afdEndpoints.routes.cacheConfiguration.queryParameters` + +Query parameters to include or exclude (comma separated). + +- Required: Yes +- Type: string + +### Parameter: `afdEndpoints.routes.cacheConfiguration.queryStringCachingBehavior` + +Defines how Frontdoor caches requests that include query strings. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'IgnoreQueryString' + 'IgnoreSpecifiedQueryStrings' + 'IncludeSpecifiedQueryStrings' + 'UseQueryString' + ] + ``` + +### Parameter: `afdEndpoints.routes.customDomainNames` + +The names of the custom domains. + +- Required: No +- Type: array + +### Parameter: `afdEndpoints.routes.enabledState` + +Whether to enable use of this rule. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `afdEndpoints.routes.forwardingProtocol` + +The protocol this rule will use when forwarding traffic to backends. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'HttpOnly' + 'HttpsOnly' + 'MatchRequest' + ] + ``` + +### Parameter: `afdEndpoints.routes.httpsRedirect` + +Whether to automatically redirect HTTP traffic to HTTPS traffic. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `afdEndpoints.routes.linkToDefaultDomain` + +Whether this route will be linked to the default endpoint domain. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `afdEndpoints.routes.originPath` + +A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath. + +- Required: No +- Type: string + +### Parameter: `afdEndpoints.routes.patternsToMatch` + +The route patterns of the rule. + +- Required: No +- Type: array + +### Parameter: `afdEndpoints.routes.ruleSets` + +The rule sets of the rule. + +- Required: No +- Type: array + +### Parameter: `afdEndpoints.routes.supportedProtocols` + +The supported protocols of the rule. + +- Required: No +- Type: array + +### Parameter: `afdEndpoints.tags` + +The tags for the AFD Endpoint. + +- Required: No +- Type: object + ### Parameter: `customDomains` Array of custom domain objects. @@ -1227,6 +1736,95 @@ Array of custom domain objects. - Type: array - Default: `[]` +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`certificateType`](#parameter-customdomainscertificatetype) | string | The type of the certificate. | +| [`hostName`](#parameter-customdomainshostname) | string | The host name of the custom domain. | +| [`name`](#parameter-customdomainsname) | string | The name of the custom domain. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`azureDnsZoneResourceId`](#parameter-customdomainsazurednszoneresourceid) | string | The resource ID of the Azure DNS zone. | +| [`extendedProperties`](#parameter-customdomainsextendedproperties) | object | Extended properties. | +| [`minimumTlsVersion`](#parameter-customdomainsminimumtlsversion) | string | The minimum TLS version. | +| [`preValidatedCustomDomainResourceId`](#parameter-customdomainsprevalidatedcustomdomainresourceid) | string | The resource ID of the pre-validated custom domain. | +| [`secretName`](#parameter-customdomainssecretname) | string | The name of the secret. | + +### Parameter: `customDomains.certificateType` + +The type of the certificate. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'AzureFirstPartyManagedCertificate' + 'CustomerCertificate' + 'ManagedCertificate' + ] + ``` + +### Parameter: `customDomains.hostName` + +The host name of the custom domain. + +- Required: Yes +- Type: string + +### Parameter: `customDomains.name` + +The name of the custom domain. + +- Required: Yes +- Type: string + +### Parameter: `customDomains.azureDnsZoneResourceId` + +The resource ID of the Azure DNS zone. + +- Required: No +- Type: string + +### Parameter: `customDomains.extendedProperties` + +Extended properties. + +- Required: No +- Type: object + +### Parameter: `customDomains.minimumTlsVersion` + +The minimum TLS version. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'TLS10' + 'TLS12' + ] + ``` + +### Parameter: `customDomains.preValidatedCustomDomainResourceId` + +The resource ID of the pre-validated custom domain. + +- Required: No +- Type: string + +### Parameter: `customDomains.secretName` + +The name of the secret. + +- Required: No +- Type: string + ### Parameter: `enableTelemetry` Enable/Disable usage telemetry for module. @@ -1444,6 +2042,89 @@ Array of rule set objects. - Type: array - Default: `[]` +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-rulesetsname) | string | Name of the rule set. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`rules`](#parameter-rulesetsrules) | array | Array of rules. | + +### Parameter: `ruleSets.name` + +Name of the rule set. + +- Required: Yes +- Type: string + +### Parameter: `ruleSets.rules` + +Array of rules. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-rulesetsrulesname) | string | The name of the rule. | +| [`order`](#parameter-rulesetsrulesorder) | int | The order in which the rules are applied for the endpoint. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`actions`](#parameter-rulesetsrulesactions) | array | A list of actions that are executed when all the conditions of a rule are satisfied.. | +| [`conditions`](#parameter-rulesetsrulesconditions) | array | A list of conditions that must be matched for the actions to be executed. | +| [`matchProcessingBehavior`](#parameter-rulesetsrulesmatchprocessingbehavior) | string | If this rule is a match should the rules engine continue running the remaining rules or stop. If not present, defaults to Continue. | + +### Parameter: `ruleSets.rules.name` + +The name of the rule. + +- Required: Yes +- Type: string + +### Parameter: `ruleSets.rules.order` + +The order in which the rules are applied for the endpoint. + +- Required: Yes +- Type: int + +### Parameter: `ruleSets.rules.actions` + +A list of actions that are executed when all the conditions of a rule are satisfied.. + +- Required: No +- Type: array + +### Parameter: `ruleSets.rules.conditions` + +A list of conditions that must be matched for the actions to be executed. + +- Required: No +- Type: array + +### Parameter: `ruleSets.rules.matchProcessingBehavior` + +If this rule is a match should the rules engine continue running the remaining rules or stop. If not present, defaults to Continue. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Continue' + 'Stop' + ] + ``` + ### Parameter: `secrets` Array of secret objects. diff --git a/avm/res/cdn/profile/afdEndpoint/README.md b/avm/res/cdn/profile/afdEndpoint/README.md index 910c0df19c..49f50fa42a 100644 --- a/avm/res/cdn/profile/afdEndpoint/README.md +++ b/avm/res/cdn/profile/afdEndpoint/README.md @@ -100,6 +100,205 @@ The list of routes for this AFD Endpoint. - Required: No - Type: array +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-routesname) | string | The name of the route. | +| [`originGroupName`](#parameter-routesorigingroupname) | string | The name of the origin group. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`cacheConfiguration`](#parameter-routescacheconfiguration) | object | The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object. | +| [`customDomainNames`](#parameter-routescustomdomainnames) | array | The names of the custom domains. | +| [`enabledState`](#parameter-routesenabledstate) | string | Whether to enable use of this rule. | +| [`forwardingProtocol`](#parameter-routesforwardingprotocol) | string | The protocol this rule will use when forwarding traffic to backends. | +| [`httpsRedirect`](#parameter-routeshttpsredirect) | string | Whether to automatically redirect HTTP traffic to HTTPS traffic. | +| [`linkToDefaultDomain`](#parameter-routeslinktodefaultdomain) | string | Whether this route will be linked to the default endpoint domain. | +| [`originPath`](#parameter-routesoriginpath) | string | A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath. | +| [`patternsToMatch`](#parameter-routespatternstomatch) | array | The route patterns of the rule. | +| [`ruleSets`](#parameter-routesrulesets) | array | The rule sets of the rule. | +| [`supportedProtocols`](#parameter-routessupportedprotocols) | array | The supported protocols of the rule. | + +### Parameter: `routes.name` + +The name of the route. + +- Required: Yes +- Type: string + +### Parameter: `routes.originGroupName` + +The name of the origin group. + +- Required: Yes +- Type: string + +### Parameter: `routes.cacheConfiguration` + +The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`compressionSettings`](#parameter-routescacheconfigurationcompressionsettings) | object | Compression settings. | +| [`queryParameters`](#parameter-routescacheconfigurationqueryparameters) | string | Query parameters to include or exclude (comma separated). | +| [`queryStringCachingBehavior`](#parameter-routescacheconfigurationquerystringcachingbehavior) | string | Defines how Frontdoor caches requests that include query strings. | + +### Parameter: `routes.cacheConfiguration.compressionSettings` + +Compression settings. + +- Required: Yes +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`contentTypesToCompress`](#parameter-routescacheconfigurationcompressionsettingscontenttypestocompress) | array | List of content types on which compression applies. The value should be a valid MIME type. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`iscontentTypeToCompressAll`](#parameter-routescacheconfigurationcompressionsettingsiscontenttypetocompressall) | bool | Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB. | + +### Parameter: `routes.cacheConfiguration.compressionSettings.contentTypesToCompress` + +List of content types on which compression applies. The value should be a valid MIME type. + +- Required: Yes +- Type: array + +### Parameter: `routes.cacheConfiguration.compressionSettings.iscontentTypeToCompressAll` + +Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB. + +- Required: No +- Type: bool + +### Parameter: `routes.cacheConfiguration.queryParameters` + +Query parameters to include or exclude (comma separated). + +- Required: Yes +- Type: string + +### Parameter: `routes.cacheConfiguration.queryStringCachingBehavior` + +Defines how Frontdoor caches requests that include query strings. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'IgnoreQueryString' + 'IgnoreSpecifiedQueryStrings' + 'IncludeSpecifiedQueryStrings' + 'UseQueryString' + ] + ``` + +### Parameter: `routes.customDomainNames` + +The names of the custom domains. + +- Required: No +- Type: array + +### Parameter: `routes.enabledState` + +Whether to enable use of this rule. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `routes.forwardingProtocol` + +The protocol this rule will use when forwarding traffic to backends. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'HttpOnly' + 'HttpsOnly' + 'MatchRequest' + ] + ``` + +### Parameter: `routes.httpsRedirect` + +Whether to automatically redirect HTTP traffic to HTTPS traffic. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `routes.linkToDefaultDomain` + +Whether this route will be linked to the default endpoint domain. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `routes.originPath` + +A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath. + +- Required: No +- Type: string + +### Parameter: `routes.patternsToMatch` + +The route patterns of the rule. + +- Required: No +- Type: array + +### Parameter: `routes.ruleSets` + +The rule sets of the rule. + +- Required: No +- Type: array + +### Parameter: `routes.supportedProtocols` + +The supported protocols of the rule. + +- Required: No +- Type: array + ### Parameter: `tags` The tags of the AFD Endpoint. diff --git a/avm/res/cdn/profile/afdEndpoint/main.bicep b/avm/res/cdn/profile/afdEndpoint/main.bicep index a280fcf07f..84644ab9ff 100644 --- a/avm/res/cdn/profile/afdEndpoint/main.bicep +++ b/avm/res/cdn/profile/afdEndpoint/main.bicep @@ -31,7 +31,7 @@ param autoGeneratedDomainNameLabelScope string = 'TenantReuse' param enabledState string = 'Enabled' @description('Optional. The list of routes for this AFD Endpoint.') -param routes array? +param routes routeType[]? resource profile 'Microsoft.Cdn/profiles@2023-05-01' existing = { name: profileName @@ -84,3 +84,27 @@ output location string = afdEndpoint.location @description('The list of routes assigned to the AFD endpoint.') output routes array = routes ?? [] + +// =============== // +// Definitions // +// =============== // + +import { routeType } from './route/main.bicep' + +@export() +type afdEndpointType = { + @description('Required. The name of the AFD Endpoint.') + name: string + + @description('Optional. The list of routes for this AFD Endpoint.') + routes: routeType[]? + + @description('Optional. The tags for the AFD Endpoint.') + tags: object? + + @description('Optional. The scope of the auto-generated domain name label.') + autoGeneratedDomainNameLabelScope: 'NoReuse' | 'ResourceGroupReuse' | 'SubscriptionReuse' | 'TenantReuse' | null + + @description('Optional. The state of the AFD Endpoint.') + enabledState: 'Enabled' | 'Disabled' | null +} diff --git a/avm/res/cdn/profile/afdEndpoint/main.json b/avm/res/cdn/profile/afdEndpoint/main.json index 7cfef24e3f..866c19c60f 100644 --- a/avm/res/cdn/profile/afdEndpoint/main.json +++ b/avm/res/cdn/profile/afdEndpoint/main.json @@ -5,13 +5,237 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "792735746278824384" + "version": "0.31.34.60546", + "templateHash": "16899001110062450573" }, "name": "CDN Profiles AFD Endpoints", "description": "This module deploys a CDN Profile AFD Endpoint.", "owner": "Azure/module-maintainers" }, + "definitions": { + "afdEndpointType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the AFD Endpoint." + } + }, + "routes": { + "type": "array", + "items": { + "$ref": "#/definitions/routeType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of routes for this AFD Endpoint." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The tags for the AFD Endpoint." + } + }, + "autoGeneratedDomainNameLabelScope": { + "type": "string", + "allowedValues": [ + "NoReuse", + "ResourceGroupReuse", + "SubscriptionReuse", + "TenantReuse" + ], + "nullable": true, + "metadata": { + "description": "Optional. The scope of the auto-generated domain name label." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. The state of the AFD Endpoint." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "_1.afdRoutecacheConfigurationType": { + "type": "object", + "properties": { + "compressionSettings": { + "type": "object", + "properties": { + "contentTypesToCompress": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. List of content types on which compression applies. The value should be a valid MIME type." + } + }, + "iscontentTypeToCompressAll": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB." + } + } + }, + "metadata": { + "description": "Required. Compression settings." + } + }, + "queryParameters": { + "type": "string", + "metadata": { + "description": "Required. Query parameters to include or exclude (comma separated)." + } + }, + "queryStringCachingBehavior": { + "type": "string", + "allowedValues": [ + "IgnoreQueryString", + "IgnoreSpecifiedQueryStrings", + "IncludeSpecifiedQueryStrings", + "UseQueryString" + ], + "metadata": { + "description": "Required. Defines how Frontdoor caches requests that include query strings." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "route/main.bicep" + } + } + }, + "routeType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the route." + } + }, + "cacheConfiguration": { + "$ref": "#/definitions/_1.afdRoutecacheConfigurationType", + "nullable": true, + "metadata": { + "description": "Optional. The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object." + } + }, + "customDomainNames": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the custom domains." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable use of this rule." + } + }, + "forwardingProtocol": { + "type": "string", + "allowedValues": [ + "HttpOnly", + "HttpsOnly", + "MatchRequest" + ], + "nullable": true, + "metadata": { + "description": "Optional. The protocol this rule will use when forwarding traffic to backends." + } + }, + "httpsRedirect": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to automatically redirect HTTP traffic to HTTPS traffic." + } + }, + "linkToDefaultDomain": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether this route will be linked to the default endpoint domain." + } + }, + "originGroupName": { + "type": "string", + "metadata": { + "description": "Required. The name of the origin group." + } + }, + "originPath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath." + } + }, + "patternsToMatch": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The route patterns of the rule." + } + }, + "ruleSets": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. The rule sets of the rule." + } + }, + "supportedProtocols": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The supported protocols of the rule." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "route/main.bicep" + } + } + } + }, "parameters": { "name": { "type": "string", @@ -65,6 +289,9 @@ }, "routes": { "type": "array", + "items": { + "$ref": "#/definitions/routeType" + }, "nullable": true, "metadata": { "description": "Optional. The list of routes for this AFD Endpoint." @@ -87,10 +314,7 @@ "properties": { "autoGeneratedDomainNameLabelScope": "[parameters('autoGeneratedDomainNameLabelScope')]", "enabledState": "[parameters('enabledState')]" - }, - "dependsOn": [ - "profile" - ] + } }, "afdEndpoint_routes": { "copy": { @@ -156,13 +380,175 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "1034122698174669197" + "version": "0.31.34.60546", + "templateHash": "15873678240851060540" }, "name": "CDN Profiles AFD Endpoint Route", "description": "This module deploys a CDN Profile AFD Endpoint route.", "owner": "Azure/module-maintainers" }, + "definitions": { + "routeType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the route." + } + }, + "cacheConfiguration": { + "$ref": "#/definitions/afdRoutecacheConfigurationType", + "nullable": true, + "metadata": { + "description": "Optional. The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object." + } + }, + "customDomainNames": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the custom domains." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable use of this rule." + } + }, + "forwardingProtocol": { + "type": "string", + "allowedValues": [ + "HttpOnly", + "HttpsOnly", + "MatchRequest" + ], + "nullable": true, + "metadata": { + "description": "Optional. The protocol this rule will use when forwarding traffic to backends." + } + }, + "httpsRedirect": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to automatically redirect HTTP traffic to HTTPS traffic." + } + }, + "linkToDefaultDomain": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether this route will be linked to the default endpoint domain." + } + }, + "originGroupName": { + "type": "string", + "metadata": { + "description": "Required. The name of the origin group." + } + }, + "originPath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath." + } + }, + "patternsToMatch": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The route patterns of the rule." + } + }, + "ruleSets": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. The rule sets of the rule." + } + }, + "supportedProtocols": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The supported protocols of the rule." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "afdRoutecacheConfigurationType": { + "type": "object", + "properties": { + "compressionSettings": { + "type": "object", + "properties": { + "contentTypesToCompress": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. List of content types on which compression applies. The value should be a valid MIME type." + } + }, + "iscontentTypeToCompressAll": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB." + } + } + }, + "metadata": { + "description": "Required. Compression settings." + } + }, + "queryParameters": { + "type": "string", + "metadata": { + "description": "Required. Query parameters to include or exclude (comma separated)." + } + }, + "queryStringCachingBehavior": { + "type": "string", + "allowedValues": [ + "IgnoreQueryString", + "IgnoreSpecifiedQueryStrings", + "IncludeSpecifiedQueryStrings", + "UseQueryString" + ], + "metadata": { + "description": "Required. Defines how Frontdoor caches requests that include query strings." + } + } + } + } + }, "parameters": { "name": { "type": "string", @@ -288,10 +674,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/afdEndpoints", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('afdEndpointName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('afdEndpointName'))]" }, "profile::customDomains": { "copy": { @@ -301,19 +684,13 @@ "existing": true, "type": "Microsoft.Cdn/profiles/customDomains", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), coalesce(parameters('customDomainNames'), createArray())[copyIndex()])]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), coalesce(parameters('customDomainNames'), createArray())[copyIndex()])]" }, "profile::originGroup": { "existing": true, "type": "Microsoft.Cdn/profiles/originGroups", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]" }, "profile::ruleSet": { "copy": { @@ -323,10 +700,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/ruleSets", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSets')[copyIndex()].name)]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSets')[copyIndex()].name)]" }, "profile": { "existing": true, @@ -366,10 +740,7 @@ "originPath": "[parameters('originPath')]", "patternsToMatch": "[parameters('patternsToMatch')]", "supportedProtocols": "[parameters('supportedProtocols')]" - }, - "dependsOn": [ - "profile::afdEndpoint" - ] + } } }, "outputs": { @@ -398,8 +769,7 @@ } }, "dependsOn": [ - "afdEndpoint", - "profile" + "afdEndpoint" ] } }, diff --git a/avm/res/cdn/profile/afdEndpoint/route/main.bicep b/avm/res/cdn/profile/afdEndpoint/route/main.bicep index 36bfd40c15..265bd43405 100644 --- a/avm/res/cdn/profile/afdEndpoint/route/main.bicep +++ b/avm/res/cdn/profile/afdEndpoint/route/main.bicep @@ -122,3 +122,66 @@ output resourceId string = route.id @description('The name of the resource group the route was created in.') output resourceGroupName string = resourceGroup().name + +// =============== // +// Definitions // +// =============== // + +@export() +type routeType = { + @description('Required. The name of the route.') + name: string + + @description('Optional. The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object.') + cacheConfiguration: afdRoutecacheConfigurationType? + + @description('Optional. The names of the custom domains.') + customDomainNames: string[]? + + @description('Optional. Whether to enable use of this rule.') + enabledState: 'Enabled' | 'Disabled' | null + + @description('Optional. The protocol this rule will use when forwarding traffic to backends.') + forwardingProtocol: 'HttpOnly' | 'HttpsOnly' | 'MatchRequest' | null + + @description('Optional. Whether to automatically redirect HTTP traffic to HTTPS traffic.') + httpsRedirect: 'Enabled' | 'Disabled' | null + + @description('Optional. Whether this route will be linked to the default endpoint domain.') + linkToDefaultDomain: 'Enabled' | 'Disabled' | null + + @description('Required. The name of the origin group.') + originGroupName: string + + @description('Optional. A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath.') + originPath: string? + + @description('Optional. The route patterns of the rule.') + patternsToMatch: array? + + @description('Optional. The rule sets of the rule.') + ruleSets: object[]? + + @description('Optional. The supported protocols of the rule.') + supportedProtocols: array? +} + +type afdRoutecacheConfigurationType = { + @description('Required. Compression settings.') + compressionSettings: { + @description('Required. List of content types on which compression applies. The value should be a valid MIME type.') + contentTypesToCompress: string[] + + @description('Optional. Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won\'t be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB.') + iscontentTypeToCompressAll: bool? + } + @description('Required. Query parameters to include or exclude (comma separated).') + queryParameters: string + + @description('Required. Defines how Frontdoor caches requests that include query strings.') + queryStringCachingBehavior: + | 'IgnoreQueryString' + | 'IgnoreSpecifiedQueryStrings' + | 'IncludeSpecifiedQueryStrings' + | 'UseQueryString' +} diff --git a/avm/res/cdn/profile/afdEndpoint/route/main.json b/avm/res/cdn/profile/afdEndpoint/route/main.json index 852e97f10c..eae2b5bfce 100644 --- a/avm/res/cdn/profile/afdEndpoint/route/main.json +++ b/avm/res/cdn/profile/afdEndpoint/route/main.json @@ -5,13 +5,175 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "1034122698174669197" + "version": "0.31.34.60546", + "templateHash": "15873678240851060540" }, "name": "CDN Profiles AFD Endpoint Route", "description": "This module deploys a CDN Profile AFD Endpoint route.", "owner": "Azure/module-maintainers" }, + "definitions": { + "routeType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the route." + } + }, + "cacheConfiguration": { + "$ref": "#/definitions/afdRoutecacheConfigurationType", + "nullable": true, + "metadata": { + "description": "Optional. The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object." + } + }, + "customDomainNames": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the custom domains." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable use of this rule." + } + }, + "forwardingProtocol": { + "type": "string", + "allowedValues": [ + "HttpOnly", + "HttpsOnly", + "MatchRequest" + ], + "nullable": true, + "metadata": { + "description": "Optional. The protocol this rule will use when forwarding traffic to backends." + } + }, + "httpsRedirect": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to automatically redirect HTTP traffic to HTTPS traffic." + } + }, + "linkToDefaultDomain": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether this route will be linked to the default endpoint domain." + } + }, + "originGroupName": { + "type": "string", + "metadata": { + "description": "Required. The name of the origin group." + } + }, + "originPath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath." + } + }, + "patternsToMatch": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The route patterns of the rule." + } + }, + "ruleSets": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. The rule sets of the rule." + } + }, + "supportedProtocols": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The supported protocols of the rule." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "afdRoutecacheConfigurationType": { + "type": "object", + "properties": { + "compressionSettings": { + "type": "object", + "properties": { + "contentTypesToCompress": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. List of content types on which compression applies. The value should be a valid MIME type." + } + }, + "iscontentTypeToCompressAll": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB." + } + } + }, + "metadata": { + "description": "Required. Compression settings." + } + }, + "queryParameters": { + "type": "string", + "metadata": { + "description": "Required. Query parameters to include or exclude (comma separated)." + } + }, + "queryStringCachingBehavior": { + "type": "string", + "allowedValues": [ + "IgnoreQueryString", + "IgnoreSpecifiedQueryStrings", + "IncludeSpecifiedQueryStrings", + "UseQueryString" + ], + "metadata": { + "description": "Required. Defines how Frontdoor caches requests that include query strings." + } + } + } + } + }, "parameters": { "name": { "type": "string", @@ -137,10 +299,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/afdEndpoints", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('afdEndpointName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('afdEndpointName'))]" }, "profile::customDomains": { "copy": { @@ -150,19 +309,13 @@ "existing": true, "type": "Microsoft.Cdn/profiles/customDomains", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), coalesce(parameters('customDomainNames'), createArray())[copyIndex()])]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), coalesce(parameters('customDomainNames'), createArray())[copyIndex()])]" }, "profile::originGroup": { "existing": true, "type": "Microsoft.Cdn/profiles/originGroups", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]" }, "profile::ruleSet": { "copy": { @@ -172,10 +325,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/ruleSets", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSets')[copyIndex()].name)]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSets')[copyIndex()].name)]" }, "profile": { "existing": true, @@ -215,10 +365,7 @@ "originPath": "[parameters('originPath')]", "patternsToMatch": "[parameters('patternsToMatch')]", "supportedProtocols": "[parameters('supportedProtocols')]" - }, - "dependsOn": [ - "profile::afdEndpoint" - ] + } } }, "outputs": { diff --git a/avm/res/cdn/profile/customdomain/README.md b/avm/res/cdn/profile/customdomain/README.md index 39077a14be..37e9d735de 100644 --- a/avm/res/cdn/profile/customdomain/README.md +++ b/avm/res/cdn/profile/customdomain/README.md @@ -49,6 +49,7 @@ The type of the certificate used for secure delivery. - Allowed: ```Bicep [ + 'AzureFirstPartyManagedCertificate' 'CustomerCertificate' 'ManagedCertificate' ] diff --git a/avm/res/cdn/profile/customdomain/main.bicep b/avm/res/cdn/profile/customdomain/main.bicep index a0a4f4477f..efe67a0569 100644 --- a/avm/res/cdn/profile/customdomain/main.bicep +++ b/avm/res/cdn/profile/customdomain/main.bicep @@ -21,6 +21,7 @@ param extendedProperties object = {} param preValidatedCustomDomainResourceId string = '' @allowed([ + 'AzureFirstPartyManagedCertificate' 'CustomerCertificate' 'ManagedCertificate' ]) @@ -40,10 +41,9 @@ param secretName string = '' resource profile 'Microsoft.Cdn/profiles@2023-05-01' existing = { name: profileName - resource secrect 'secrets@2023-05-01' existing = - if (!empty(secretName)) { - name: secretName - } + resource secrect 'secrets@2023-05-01' existing = if (!empty(secretName)) { + name: secretName + } } resource customDomain 'Microsoft.Cdn/profiles/customDomains@2023-05-01' = { @@ -82,3 +82,33 @@ output resourceId string = customDomain.id @description('The name of the resource group the custom domain was created in.') output resourceGroupName string = resourceGroup().name + +// =============== // +// Definitions // +// =============== // +@export() +type customDomainType = { + @description('Required. The name of the custom domain.') + name: string + + @description('Required. The host name of the custom domain.') + hostName: string + + @description('Required. The type of the certificate.') + certificateType: 'AzureFirstPartyManagedCertificate' | 'CustomerCertificate' | 'ManagedCertificate' + + @description('Optional. The resource ID of the Azure DNS zone.') + azureDnsZoneResourceId: string? + + @description('Optional. The resource ID of the pre-validated custom domain.') + preValidatedCustomDomainResourceId: string? + + @description('Optional. The name of the secret.') + secretName: string? + + @description('Optional. The minimum TLS version.') + minimumTlsVersion: 'TLS10' | 'TLS12' | null + + @description('Optional. Extended properties.') + extendedProperties: object? +} diff --git a/avm/res/cdn/profile/customdomain/main.json b/avm/res/cdn/profile/customdomain/main.json index e45727e4ad..b88c221734 100644 --- a/avm/res/cdn/profile/customdomain/main.json +++ b/avm/res/cdn/profile/customdomain/main.json @@ -1,16 +1,89 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "16955838730426729961" + "version": "0.31.34.60546", + "templateHash": "10387694873442665915" }, "name": "CDN Profiles Custom Domains", "description": "This module deploys a CDN Profile Custom Domains.", "owner": "Azure/module-maintainers" }, + "definitions": { + "customDomainType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the custom domain." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The host name of the custom domain." + } + }, + "certificateType": { + "type": "string", + "allowedValues": [ + "AzureFirstPartyManagedCertificate", + "CustomerCertificate", + "ManagedCertificate" + ], + "metadata": { + "description": "Required. The type of the certificate." + } + }, + "azureDnsZoneResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the Azure DNS zone." + } + }, + "preValidatedCustomDomainResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the pre-validated custom domain." + } + }, + "secretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the secret." + } + }, + "minimumTlsVersion": { + "type": "string", + "allowedValues": [ + "TLS10", + "TLS12" + ], + "nullable": true, + "metadata": { + "description": "Optional. The minimum TLS version." + } + }, + "extendedProperties": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Extended properties." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -54,6 +127,7 @@ "certificateType": { "type": "string", "allowedValues": [ + "AzureFirstPartyManagedCertificate", "CustomerCertificate", "ManagedCertificate" ], @@ -80,8 +154,21 @@ } } }, - "resources": [ - { + "resources": { + "profile::secrect": { + "condition": "[not(empty(parameters('secretName')))]", + "existing": true, + "type": "Microsoft.Cdn/profiles/secrets", + "apiVersion": "2023-05-01", + "name": "[format('{0}/{1}', parameters('profileName'), parameters('secretName'))]" + }, + "profile": { + "existing": true, + "type": "Microsoft.Cdn/profiles", + "apiVersion": "2023-05-01", + "name": "[parameters('profileName')]" + }, + "customDomain": { "type": "Microsoft.Cdn/profiles/customDomains", "apiVersion": "2023-05-01", "name": "[format('{0}/{1}', parameters('profileName'), parameters('name'))]", @@ -97,7 +184,7 @@ } } } - ], + }, "outputs": { "name": { "type": "string", diff --git a/avm/res/cdn/profile/endpoint/main.json b/avm/res/cdn/profile/endpoint/main.json index 273dbe9fce..ca9c1a9478 100644 --- a/avm/res/cdn/profile/endpoint/main.json +++ b/avm/res/cdn/profile/endpoint/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "3460565146034921053" + "version": "0.31.34.60546", + "templateHash": "5709530270456479127" }, "name": "CDN Profiles Endpoints", "description": "This module deploys a CDN Profile Endpoint.", @@ -59,10 +59,7 @@ "name": "[format('{0}/{1}', parameters('profileName'), parameters('name'))]", "location": "[parameters('location')]", "properties": "[parameters('properties')]", - "tags": "[parameters('tags')]", - "dependsOn": [ - "profile" - ] + "tags": "[parameters('tags')]" }, "endpoint_origins": { "copy": { @@ -125,8 +122,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4151069688274070352" + "version": "0.31.34.60546", + "templateHash": "12416203553821456162" }, "name": "CDN Profiles Endpoints Origins", "description": "This module deploys a CDN Profile Endpoint Origin.", @@ -233,19 +230,13 @@ "existing": true, "type": "Microsoft.Cdn/profiles/endpoints", "apiVersion": "2021-06-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('endpointName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('endpointName'))]" }, "origin": { "type": "Microsoft.Cdn/profiles/endpoints/origins", "apiVersion": "2021-06-01", "name": "[format('{0}/{1}/{2}', parameters('profileName'), parameters('endpointName'), parameters('name'))]", - "properties": "[union(createObject('hostName', parameters('hostName'), 'httpPort', parameters('httpPort'), 'enabled', parameters('enabled'), 'httpsPort', parameters('httpsPort')), if(or(greater(parameters('priority'), 0), greater(parameters('weight'), 0)), createObject('priority', parameters('priority'), 'weight', parameters('weight')), createObject()), if(and(not(empty(parameters('privateLinkAlias'))), not(empty(parameters('privateLinkLocation')))), createObject('privateLinkAlias', parameters('privateLinkAlias'), 'privateLinkLocation', parameters('privateLinkLocation')), createObject()), if(not(empty(parameters('privateLinkResourceId'))), createObject('privateLinkResourceId', parameters('privateLinkResourceId')), createObject()), if(not(empty(parameters('originHostHeader'))), createObject('originHostHeader', parameters('originHostHeader')), createObject()))]", - "dependsOn": [ - "endpoint" - ] + "properties": "[union(createObject('hostName', parameters('hostName'), 'httpPort', parameters('httpPort'), 'enabled', parameters('enabled'), 'httpsPort', parameters('httpsPort')), if(or(greater(parameters('priority'), 0), greater(parameters('weight'), 0)), createObject('priority', parameters('priority'), 'weight', parameters('weight')), createObject()), if(and(not(empty(parameters('privateLinkAlias'))), not(empty(parameters('privateLinkLocation')))), createObject('privateLinkAlias', parameters('privateLinkAlias'), 'privateLinkLocation', parameters('privateLinkLocation')), createObject()), if(not(empty(parameters('privateLinkResourceId'))), createObject('privateLinkResourceId', parameters('privateLinkResourceId')), createObject()), if(not(empty(parameters('originHostHeader'))), createObject('originHostHeader', parameters('originHostHeader')), createObject()))]" } }, "outputs": { @@ -281,8 +272,7 @@ } }, "dependsOn": [ - "endpoint", - "profile" + "endpoint" ] } }, diff --git a/avm/res/cdn/profile/endpoint/origin/main.json b/avm/res/cdn/profile/endpoint/origin/main.json index f4c079ff44..e71c4745c1 100644 --- a/avm/res/cdn/profile/endpoint/origin/main.json +++ b/avm/res/cdn/profile/endpoint/origin/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4151069688274070352" + "version": "0.31.34.60546", + "templateHash": "12416203553821456162" }, "name": "CDN Profiles Endpoints Origins", "description": "This module deploys a CDN Profile Endpoint Origin.", @@ -113,19 +113,13 @@ "existing": true, "type": "Microsoft.Cdn/profiles/endpoints", "apiVersion": "2021-06-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('endpointName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('endpointName'))]" }, "origin": { "type": "Microsoft.Cdn/profiles/endpoints/origins", "apiVersion": "2021-06-01", "name": "[format('{0}/{1}/{2}', parameters('profileName'), parameters('endpointName'), parameters('name'))]", - "properties": "[union(createObject('hostName', parameters('hostName'), 'httpPort', parameters('httpPort'), 'enabled', parameters('enabled'), 'httpsPort', parameters('httpsPort')), if(or(greater(parameters('priority'), 0), greater(parameters('weight'), 0)), createObject('priority', parameters('priority'), 'weight', parameters('weight')), createObject()), if(and(not(empty(parameters('privateLinkAlias'))), not(empty(parameters('privateLinkLocation')))), createObject('privateLinkAlias', parameters('privateLinkAlias'), 'privateLinkLocation', parameters('privateLinkLocation')), createObject()), if(not(empty(parameters('privateLinkResourceId'))), createObject('privateLinkResourceId', parameters('privateLinkResourceId')), createObject()), if(not(empty(parameters('originHostHeader'))), createObject('originHostHeader', parameters('originHostHeader')), createObject()))]", - "dependsOn": [ - "endpoint" - ] + "properties": "[union(createObject('hostName', parameters('hostName'), 'httpPort', parameters('httpPort'), 'enabled', parameters('enabled'), 'httpsPort', parameters('httpsPort')), if(or(greater(parameters('priority'), 0), greater(parameters('weight'), 0)), createObject('priority', parameters('priority'), 'weight', parameters('weight')), createObject()), if(and(not(empty(parameters('privateLinkAlias'))), not(empty(parameters('privateLinkLocation')))), createObject('privateLinkAlias', parameters('privateLinkAlias'), 'privateLinkLocation', parameters('privateLinkLocation')), createObject()), if(not(empty(parameters('privateLinkResourceId'))), createObject('privateLinkResourceId', parameters('privateLinkResourceId')), createObject()), if(not(empty(parameters('originHostHeader'))), createObject('originHostHeader', parameters('originHostHeader')), createObject()))]" } }, "outputs": { diff --git a/avm/res/cdn/profile/main.bicep b/avm/res/cdn/profile/main.bicep index 2c30c0c2e2..ae15d9234b 100644 --- a/avm/res/cdn/profile/main.bicep +++ b/avm/res/cdn/profile/main.bicep @@ -38,16 +38,16 @@ param endpointProperties object? param secrets array = [] @description('Optional. Array of custom domain objects.') -param customDomains array = [] +param customDomains customDomainType[] = [] @description('Conditional. Array of origin group objects. Required if the afdEndpoints is specified.') -param originGroups array = [] +param originGroups originGroupType[] = [] @description('Optional. Array of rule set objects.') -param ruleSets array = [] +param ruleSets ruleSetType[] = [] @description('Optional. Array of AFD endpoint objects.') -param afdEndpoints array = [] +param afdEndpoints afdEndpointType[] = [] @description('Optional. Array of Security Policy objects (see https://learn.microsoft.com/en-us/azure/templates/microsoft.cdn/profiles/securitypolicies for details).') param securityPolicies securityPolicyType = [] @@ -320,6 +320,14 @@ output systemAssignedMIPrincipalId string = profile.?identity.?principalId ?? '' // Definitions // // =============== // +import { afdEndpointType } from 'afdEndpoint/main.bicep' +import { customDomainType } from 'customdomain/main.bicep' +import { originGroupType } from 'origingroup/main.bicep' +import { originType } from 'origingroup//origin/main.bicep' +import { associationsType } from 'securityPolicies/main.bicep' +import { ruleSetType } from 'ruleset/main.bicep' +import { ruleType } from 'ruleset/rule/main.bicep' + type managedIdentitiesType = { @description('Optional. Enables system assigned managed identity on the resource.') systemAssigned: bool? @@ -328,7 +336,7 @@ type managedIdentitiesType = { userAssignedResourceIds: string[]? }? -import { associationsType } from 'securityPolicies/main.bicep' +@export() type securityPolicyType = { @description('Required. Name of the security policy.') name: string diff --git a/avm/res/cdn/profile/main.json b/avm/res/cdn/profile/main.json index 479e17ece5..1d5952c679 100644 --- a/avm/res/cdn/profile/main.json +++ b/avm/res/cdn/profile/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14447016685732236984" + "version": "0.31.34.60546", + "templateHash": "10761375864597089825" }, "name": "CDN Profiles", "description": "This module deploys a CDN Profile.", @@ -60,6 +60,9 @@ } } } + }, + "metadata": { + "__bicep_export!": true } }, "lockType": { @@ -160,6 +163,388 @@ }, "nullable": true }, + "_1.afdRoutecacheConfigurationType": { + "type": "object", + "properties": { + "compressionSettings": { + "type": "object", + "properties": { + "contentTypesToCompress": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. List of content types on which compression applies. The value should be a valid MIME type." + } + }, + "iscontentTypeToCompressAll": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB." + } + } + }, + "metadata": { + "description": "Required. Compression settings." + } + }, + "queryParameters": { + "type": "string", + "metadata": { + "description": "Required. Query parameters to include or exclude (comma separated)." + } + }, + "queryStringCachingBehavior": { + "type": "string", + "allowedValues": [ + "IgnoreQueryString", + "IgnoreSpecifiedQueryStrings", + "IncludeSpecifiedQueryStrings", + "UseQueryString" + ], + "metadata": { + "description": "Required. Defines how Frontdoor caches requests that include query strings." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "afdEndpoint/route/main.bicep" + } + } + }, + "_1.routeType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the route." + } + }, + "cacheConfiguration": { + "$ref": "#/definitions/_1.afdRoutecacheConfigurationType", + "nullable": true, + "metadata": { + "description": "Optional. The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object." + } + }, + "customDomainNames": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the custom domains." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable use of this rule." + } + }, + "forwardingProtocol": { + "type": "string", + "allowedValues": [ + "HttpOnly", + "HttpsOnly", + "MatchRequest" + ], + "nullable": true, + "metadata": { + "description": "Optional. The protocol this rule will use when forwarding traffic to backends." + } + }, + "httpsRedirect": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to automatically redirect HTTP traffic to HTTPS traffic." + } + }, + "linkToDefaultDomain": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether this route will be linked to the default endpoint domain." + } + }, + "originGroupName": { + "type": "string", + "metadata": { + "description": "Required. The name of the origin group." + } + }, + "originPath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath." + } + }, + "patternsToMatch": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The route patterns of the rule." + } + }, + "ruleSets": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. The rule sets of the rule." + } + }, + "supportedProtocols": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The supported protocols of the rule." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "afdEndpoint/route/main.bicep" + } + } + }, + "_2.healthProbeSettingsType": { + "type": "object", + "properties": { + "probePath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The path relative to the origin that is used to determine the health of the origin." + } + }, + "probeProtocol": { + "type": "string", + "allowedValues": [ + "Http", + "Https", + "NotSet" + ], + "nullable": true, + "metadata": { + "description": "Optional. Protocol to use for health probe." + } + }, + "probeRequestType": { + "type": "string", + "allowedValues": [ + "GET", + "HEAD", + "NotSet" + ], + "nullable": true, + "metadata": { + "description": "Optional. The request type to probe." + } + }, + "probeIntervalInSeconds": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The number of seconds between health probes.Default is 240sec." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "origingroup/main.bicep" + } + } + }, + "_2.loadBalancingSettingsType": { + "type": "object", + "properties": { + "additionalLatencyInMilliseconds": { + "type": "int", + "metadata": { + "description": "Required. Additional latency in milliseconds for probes to the backend. Must be between 0 and 1000." + } + }, + "sampleSize": { + "type": "int", + "metadata": { + "description": "Required. Number of samples to consider for load balancing decisions." + } + }, + "successfulSamplesRequired": { + "type": "int", + "metadata": { + "description": "Required. Number of samples within the sample window that must be successful to mark the backend as healthy." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "origingroup/main.bicep" + } + } + }, + "_3.originType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origion." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool." + } + }, + "enforceCertificateNameCheck": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable certificate name check at origin level." + } + }, + "httpPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTP port. Must be between 1 and 65535." + } + }, + "httpsPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTPS port. Must be between 1 and 65535." + } + }, + "originHostHeader": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint." + } + }, + "priority": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5." + } + }, + "weight": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Weight of the origin in given origin group for load balancing. Must be between 1 and 1000." + } + }, + "sharedPrivateLinkResource": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The properties of the private link resource for private origin." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "origingroup/origin/main.bicep" + } + } + }, + "afdEndpointType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the AFD Endpoint." + } + }, + "routes": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.routeType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of routes for this AFD Endpoint." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The tags for the AFD Endpoint." + } + }, + "autoGeneratedDomainNameLabelScope": { + "type": "string", + "allowedValues": [ + "NoReuse", + "ResourceGroupReuse", + "SubscriptionReuse", + "TenantReuse" + ], + "nullable": true, + "metadata": { + "description": "Optional. The scope of the auto-generated domain name label." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. The state of the AFD Endpoint." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "afdEndpoint/main.bicep" + } + } + }, "associationsType": { "type": "array", "items": { @@ -195,7 +580,290 @@ }, "metadata": { "__bicep_imported_from!": { - "sourceTemplate": "securityPolicies/main.bicep" + "sourceTemplate": "securityPolicies/main.bicep" + } + } + }, + "customDomainType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the custom domain." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The host name of the custom domain." + } + }, + "certificateType": { + "type": "string", + "allowedValues": [ + "AzureFirstPartyManagedCertificate", + "CustomerCertificate", + "ManagedCertificate" + ], + "metadata": { + "description": "Required. The type of the certificate." + } + }, + "azureDnsZoneResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the Azure DNS zone." + } + }, + "preValidatedCustomDomainResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the pre-validated custom domain." + } + }, + "secretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the secret." + } + }, + "minimumTlsVersion": { + "type": "string", + "allowedValues": [ + "TLS10", + "TLS12" + ], + "nullable": true, + "metadata": { + "description": "Optional. The minimum TLS version." + } + }, + "extendedProperties": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Extended properties." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "customdomain/main.bicep" + } + } + }, + "originGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origin group." + } + }, + "loadBalancingSettings": { + "$ref": "#/definitions/_2.loadBalancingSettingsType", + "metadata": { + "description": "Required. Load balancing settings for a backend pool." + } + }, + "healthProbeSettings": { + "$ref": "#/definitions/_2.healthProbeSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. Health probe settings to the origin that is used to determine the health of the origin." + } + }, + "sessionAffinityState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to allow session affinity on this host." + } + }, + "trafficRestorationTimeToHealedOrNewEndpointsInMinutes": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Time in minutes to shift the traffic to the endpoint gradually when an unhealthy endpoint comes healthy or a new endpoint is added. Default is 10 mins." + } + }, + "origins": { + "type": "array", + "items": { + "$ref": "#/definitions/_3.originType" + }, + "metadata": { + "description": "Required. The list of origins within the origin group." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "origingroup/main.bicep" + } + } + }, + "originType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origion." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool." + } + }, + "enforceCertificateNameCheck": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable certificate name check at origin level." + } + }, + "httpPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTP port. Must be between 1 and 65535." + } + }, + "httpsPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTPS port. Must be between 1 and 65535." + } + }, + "originHostHeader": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint." + } + }, + "priority": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5." + } + }, + "weight": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Weight of the origin in given origin group for load balancing. Must be between 1 and 1000." + } + }, + "sharedPrivateLinkResource": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The properties of the private link resource for private origin." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "origingroup//origin/main.bicep" + } + } + }, + "ruleSetType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the rule set." + } + }, + "rules": { + "type": "array", + "items": { + "$ref": "#/definitions/ruleType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of rules." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "ruleset/main.bicep" + } + } + }, + "ruleType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the rule." + } + }, + "order": { + "type": "int", + "metadata": { + "description": "Required. The order in which the rules are applied for the endpoint." + } + }, + "actions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of actions that are executed when all the conditions of a rule are satisfied.." + } + }, + "conditions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of conditions that must be matched for the actions to be executed." + } + }, + "matchProcessingBehavior": { + "type": "string", + "allowedValues": [ + "Continue", + "Stop" + ], + "nullable": true, + "metadata": { + "description": "Optional. If this rule is a match should the rules engine continue running the remaining rules or stop. If not present, defaults to Continue." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "ruleset/rule/main.bicep" } } } @@ -264,6 +932,9 @@ }, "customDomains": { "type": "array", + "items": { + "$ref": "#/definitions/customDomainType" + }, "defaultValue": [], "metadata": { "description": "Optional. Array of custom domain objects." @@ -271,6 +942,9 @@ }, "originGroups": { "type": "array", + "items": { + "$ref": "#/definitions/originGroupType" + }, "defaultValue": [], "metadata": { "description": "Conditional. Array of origin group objects. Required if the afdEndpoints is specified." @@ -278,6 +952,9 @@ }, "ruleSets": { "type": "array", + "items": { + "$ref": "#/definitions/ruleSetType" + }, "defaultValue": [], "metadata": { "description": "Optional. Array of rule set objects." @@ -285,6 +962,9 @@ }, "afdEndpoints": { "type": "array", + "items": { + "$ref": "#/definitions/afdEndpointType" + }, "defaultValue": [], "metadata": { "description": "Optional. Array of AFD endpoint objects." @@ -454,8 +1134,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "3460565146034921053" + "version": "0.31.34.60546", + "templateHash": "5709530270456479127" }, "name": "CDN Profiles Endpoints", "description": "This module deploys a CDN Profile Endpoint.", @@ -508,10 +1188,7 @@ "name": "[format('{0}/{1}', parameters('profileName'), parameters('name'))]", "location": "[parameters('location')]", "properties": "[parameters('properties')]", - "tags": "[parameters('tags')]", - "dependsOn": [ - "profile" - ] + "tags": "[parameters('tags')]" }, "endpoint_origins": { "copy": { @@ -574,8 +1251,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4151069688274070352" + "version": "0.31.34.60546", + "templateHash": "12416203553821456162" }, "name": "CDN Profiles Endpoints Origins", "description": "This module deploys a CDN Profile Endpoint Origin.", @@ -682,19 +1359,13 @@ "existing": true, "type": "Microsoft.Cdn/profiles/endpoints", "apiVersion": "2021-06-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('endpointName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('endpointName'))]" }, "origin": { "type": "Microsoft.Cdn/profiles/endpoints/origins", "apiVersion": "2021-06-01", "name": "[format('{0}/{1}/{2}', parameters('profileName'), parameters('endpointName'), parameters('name'))]", - "properties": "[union(createObject('hostName', parameters('hostName'), 'httpPort', parameters('httpPort'), 'enabled', parameters('enabled'), 'httpsPort', parameters('httpsPort')), if(or(greater(parameters('priority'), 0), greater(parameters('weight'), 0)), createObject('priority', parameters('priority'), 'weight', parameters('weight')), createObject()), if(and(not(empty(parameters('privateLinkAlias'))), not(empty(parameters('privateLinkLocation')))), createObject('privateLinkAlias', parameters('privateLinkAlias'), 'privateLinkLocation', parameters('privateLinkLocation')), createObject()), if(not(empty(parameters('privateLinkResourceId'))), createObject('privateLinkResourceId', parameters('privateLinkResourceId')), createObject()), if(not(empty(parameters('originHostHeader'))), createObject('originHostHeader', parameters('originHostHeader')), createObject()))]", - "dependsOn": [ - "endpoint" - ] + "properties": "[union(createObject('hostName', parameters('hostName'), 'httpPort', parameters('httpPort'), 'enabled', parameters('enabled'), 'httpsPort', parameters('httpsPort')), if(or(greater(parameters('priority'), 0), greater(parameters('weight'), 0)), createObject('priority', parameters('priority'), 'weight', parameters('weight')), createObject()), if(and(not(empty(parameters('privateLinkAlias'))), not(empty(parameters('privateLinkLocation')))), createObject('privateLinkAlias', parameters('privateLinkAlias'), 'privateLinkLocation', parameters('privateLinkLocation')), createObject()), if(not(empty(parameters('privateLinkResourceId'))), createObject('privateLinkResourceId', parameters('privateLinkResourceId')), createObject()), if(not(empty(parameters('originHostHeader'))), createObject('originHostHeader', parameters('originHostHeader')), createObject()))]" } }, "outputs": { @@ -730,8 +1401,7 @@ } }, "dependsOn": [ - "endpoint", - "profile" + "endpoint" ] } }, @@ -827,8 +1497,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "7661706938502506866" + "version": "0.31.34.60546", + "templateHash": "135211401759640973" }, "name": "CDN Profiles Secret", "description": "This module deploys a CDN Profile Secret.", @@ -857,7 +1527,7 @@ "UrlSigningKey" ], "metadata": { - "description": "Required. The type of the secrect." + "description": "Optional. The type of the secrect." } }, "secretSourceResourceId": { @@ -972,17 +1642,90 @@ }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "16955838730426729961" + "version": "0.31.34.60546", + "templateHash": "10387694873442665915" }, "name": "CDN Profiles Custom Domains", "description": "This module deploys a CDN Profile Custom Domains.", "owner": "Azure/module-maintainers" }, + "definitions": { + "customDomainType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the custom domain." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The host name of the custom domain." + } + }, + "certificateType": { + "type": "string", + "allowedValues": [ + "AzureFirstPartyManagedCertificate", + "CustomerCertificate", + "ManagedCertificate" + ], + "metadata": { + "description": "Required. The type of the certificate." + } + }, + "azureDnsZoneResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the Azure DNS zone." + } + }, + "preValidatedCustomDomainResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the pre-validated custom domain." + } + }, + "secretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the secret." + } + }, + "minimumTlsVersion": { + "type": "string", + "allowedValues": [ + "TLS10", + "TLS12" + ], + "nullable": true, + "metadata": { + "description": "Optional. The minimum TLS version." + } + }, + "extendedProperties": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Extended properties." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -1026,6 +1769,7 @@ "certificateType": { "type": "string", "allowedValues": [ + "AzureFirstPartyManagedCertificate", "CustomerCertificate", "ManagedCertificate" ], @@ -1052,8 +1796,21 @@ } } }, - "resources": [ - { + "resources": { + "profile::secrect": { + "condition": "[not(empty(parameters('secretName')))]", + "existing": true, + "type": "Microsoft.Cdn/profiles/secrets", + "apiVersion": "2023-05-01", + "name": "[format('{0}/{1}', parameters('profileName'), parameters('secretName'))]" + }, + "profile": { + "existing": true, + "type": "Microsoft.Cdn/profiles", + "apiVersion": "2023-05-01", + "name": "[parameters('profileName')]" + }, + "customDomain": { "type": "Microsoft.Cdn/profiles/customDomains", "apiVersion": "2023-05-01", "name": "[format('{0}/{1}', parameters('profileName'), parameters('name'))]", @@ -1069,7 +1826,7 @@ } } } - ], + }, "outputs": { "name": { "type": "string", @@ -1143,13 +1900,223 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "16948516107556143812" + "version": "0.31.34.60546", + "templateHash": "15886213526918072525" }, "name": "CDN Profiles Origin Group", "description": "This module deploys a CDN Profile Origin Group.", "owner": "Azure/module-maintainers" }, + "definitions": { + "originGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origin group." + } + }, + "loadBalancingSettings": { + "$ref": "#/definitions/loadBalancingSettingsType", + "metadata": { + "description": "Required. Load balancing settings for a backend pool." + } + }, + "healthProbeSettings": { + "$ref": "#/definitions/healthProbeSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. Health probe settings to the origin that is used to determine the health of the origin." + } + }, + "sessionAffinityState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to allow session affinity on this host." + } + }, + "trafficRestorationTimeToHealedOrNewEndpointsInMinutes": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Time in minutes to shift the traffic to the endpoint gradually when an unhealthy endpoint comes healthy or a new endpoint is added. Default is 10 mins." + } + }, + "origins": { + "type": "array", + "items": { + "$ref": "#/definitions/originType" + }, + "metadata": { + "description": "Required. The list of origins within the origin group." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "loadBalancingSettingsType": { + "type": "object", + "properties": { + "additionalLatencyInMilliseconds": { + "type": "int", + "metadata": { + "description": "Required. Additional latency in milliseconds for probes to the backend. Must be between 0 and 1000." + } + }, + "sampleSize": { + "type": "int", + "metadata": { + "description": "Required. Number of samples to consider for load balancing decisions." + } + }, + "successfulSamplesRequired": { + "type": "int", + "metadata": { + "description": "Required. Number of samples within the sample window that must be successful to mark the backend as healthy." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "healthProbeSettingsType": { + "type": "object", + "properties": { + "probePath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The path relative to the origin that is used to determine the health of the origin." + } + }, + "probeProtocol": { + "type": "string", + "allowedValues": [ + "Http", + "Https", + "NotSet" + ], + "nullable": true, + "metadata": { + "description": "Optional. Protocol to use for health probe." + } + }, + "probeRequestType": { + "type": "string", + "allowedValues": [ + "GET", + "HEAD", + "NotSet" + ], + "nullable": true, + "metadata": { + "description": "Optional. The request type to probe." + } + }, + "probeIntervalInSeconds": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The number of seconds between health probes.Default is 240sec." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "originType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origion." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool." + } + }, + "enforceCertificateNameCheck": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable certificate name check at origin level." + } + }, + "httpPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTP port. Must be between 1 and 65535." + } + }, + "httpsPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTPS port. Must be between 1 and 65535." + } + }, + "originHostHeader": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint." + } + }, + "priority": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5." + } + }, + "weight": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Weight of the origin in given origin group for load balancing. Must be between 1 and 1000." + } + }, + "sharedPrivateLinkResource": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The properties of the private link resource for private origin." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "origin/main.bicep" + } + } + } + }, "parameters": { "name": { "type": "string", @@ -1217,10 +2184,7 @@ "loadBalancingSettings": "[parameters('loadBalancingSettings')]", "sessionAffinityState": "[parameters('sessionAffinityState')]", "trafficRestorationTimeToHealedOrNewEndpointsInMinutes": "[parameters('trafficRestorationTimeToHealedOrNewEndpointsInMinutes')]" - }, - "dependsOn": [ - "profile" - ] + } }, "originGroup_origins": { "copy": { @@ -1280,13 +2244,95 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4669077701065465911" + "version": "0.31.34.60546", + "templateHash": "3615112055594041997" }, "name": "CDN Profiles Origin", "description": "This module deploys a CDN Profile Origin.", "owner": "Azure/module-maintainers" }, + "definitions": { + "originType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origion." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool." + } + }, + "enforceCertificateNameCheck": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable certificate name check at origin level." + } + }, + "httpPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTP port. Must be between 1 and 65535." + } + }, + "httpsPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTPS port. Must be between 1 and 65535." + } + }, + "originHostHeader": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint." + } + }, + "priority": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5." + } + }, + "weight": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Weight of the origin in given origin group for load balancing. Must be between 1 and 1000." + } + }, + "sharedPrivateLinkResource": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The properties of the private link resource for private origin." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -1378,10 +2424,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/originGroups", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]" }, "profile": { "existing": true, @@ -1403,10 +2446,7 @@ "priority": "[parameters('priority')]", "sharedPrivateLinkResource": "[parameters('sharedPrivateLinkResource')]", "weight": "[parameters('weight')]" - }, - "dependsOn": [ - "profile::originGroup" - ] + } } }, "outputs": { @@ -1506,12 +2546,85 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11520922481694023973" + "version": "0.31.34.60546", + "templateHash": "4753233857701337613" + }, + "name": "CDN Profiles Rule Sets", + "description": "This module deploys a CDN Profile rule set.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "ruleSetType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the rule set." + } + }, + "rules": { + "type": "array", + "items": { + "$ref": "#/definitions/ruleType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of rules." + } + } + }, + "metadata": { + "__bicep_export!": true + } }, - "name": "CDN Profiles Rule Sets", - "description": "This module deploys a CDN Profile rule set.", - "owner": "Azure/module-maintainers" + "ruleType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the rule." + } + }, + "order": { + "type": "int", + "metadata": { + "description": "Required. The order in which the rules are applied for the endpoint." + } + }, + "actions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of actions that are executed when all the conditions of a rule are satisfied.." + } + }, + "conditions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of conditions that must be matched for the actions to be executed." + } + }, + "matchProcessingBehavior": { + "type": "string", + "allowedValues": [ + "Continue", + "Stop" + ], + "nullable": true, + "metadata": { + "description": "Optional. If this rule is a match should the rules engine continue running the remaining rules or stop. If not present, defaults to Continue." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "rule/main.bicep" + } + } + } }, "parameters": { "name": { @@ -1528,6 +2641,9 @@ }, "rules": { "type": "array", + "items": { + "$ref": "#/definitions/ruleType" + }, "nullable": true, "metadata": { "description": "Optinal. The rules to apply to the rule set." @@ -1544,10 +2660,7 @@ "ruleSet": { "type": "Microsoft.Cdn/profiles/ruleSets", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('name'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('name'))]" }, "ruleSet_rules": { "copy": { @@ -1592,13 +2705,60 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "8818585542646204223" + "version": "0.31.34.60546", + "templateHash": "11756620080021514486" }, "name": "CDN Profiles Rules", "description": "This module deploys a CDN Profile rule.", "owner": "Azure/module-maintainers" }, + "definitions": { + "ruleType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the rule." + } + }, + "order": { + "type": "int", + "metadata": { + "description": "Required. The order in which the rules are applied for the endpoint." + } + }, + "actions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of actions that are executed when all the conditions of a rule are satisfied.." + } + }, + "conditions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of conditions that must be matched for the actions to be executed." + } + }, + "matchProcessingBehavior": { + "type": "string", + "allowedValues": [ + "Continue", + "Stop" + ], + "nullable": true, + "metadata": { + "description": "Optional. If this rule is a match should the rules engine continue running the remaining rules or stop. If not present, defaults to Continue." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -1655,10 +2815,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/ruleSets", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSetName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSetName'))]" }, "profile": { "existing": true, @@ -1675,10 +2832,7 @@ "actions": "[parameters('actions')]", "conditions": "[parameters('conditions')]", "matchProcessingBehavior": "[parameters('matchProcessingBehavior')]" - }, - "dependsOn": [ - "profile::ruleSet" - ] + } } }, "outputs": { @@ -1780,13 +2934,237 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "792735746278824384" + "version": "0.31.34.60546", + "templateHash": "16899001110062450573" }, "name": "CDN Profiles AFD Endpoints", "description": "This module deploys a CDN Profile AFD Endpoint.", "owner": "Azure/module-maintainers" }, + "definitions": { + "afdEndpointType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the AFD Endpoint." + } + }, + "routes": { + "type": "array", + "items": { + "$ref": "#/definitions/routeType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of routes for this AFD Endpoint." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The tags for the AFD Endpoint." + } + }, + "autoGeneratedDomainNameLabelScope": { + "type": "string", + "allowedValues": [ + "NoReuse", + "ResourceGroupReuse", + "SubscriptionReuse", + "TenantReuse" + ], + "nullable": true, + "metadata": { + "description": "Optional. The scope of the auto-generated domain name label." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. The state of the AFD Endpoint." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "_1.afdRoutecacheConfigurationType": { + "type": "object", + "properties": { + "compressionSettings": { + "type": "object", + "properties": { + "contentTypesToCompress": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. List of content types on which compression applies. The value should be a valid MIME type." + } + }, + "iscontentTypeToCompressAll": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB." + } + } + }, + "metadata": { + "description": "Required. Compression settings." + } + }, + "queryParameters": { + "type": "string", + "metadata": { + "description": "Required. Query parameters to include or exclude (comma separated)." + } + }, + "queryStringCachingBehavior": { + "type": "string", + "allowedValues": [ + "IgnoreQueryString", + "IgnoreSpecifiedQueryStrings", + "IncludeSpecifiedQueryStrings", + "UseQueryString" + ], + "metadata": { + "description": "Required. Defines how Frontdoor caches requests that include query strings." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "route/main.bicep" + } + } + }, + "routeType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the route." + } + }, + "cacheConfiguration": { + "$ref": "#/definitions/_1.afdRoutecacheConfigurationType", + "nullable": true, + "metadata": { + "description": "Optional. The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object." + } + }, + "customDomainNames": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the custom domains." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable use of this rule." + } + }, + "forwardingProtocol": { + "type": "string", + "allowedValues": [ + "HttpOnly", + "HttpsOnly", + "MatchRequest" + ], + "nullable": true, + "metadata": { + "description": "Optional. The protocol this rule will use when forwarding traffic to backends." + } + }, + "httpsRedirect": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to automatically redirect HTTP traffic to HTTPS traffic." + } + }, + "linkToDefaultDomain": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether this route will be linked to the default endpoint domain." + } + }, + "originGroupName": { + "type": "string", + "metadata": { + "description": "Required. The name of the origin group." + } + }, + "originPath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath." + } + }, + "patternsToMatch": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The route patterns of the rule." + } + }, + "ruleSets": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. The rule sets of the rule." + } + }, + "supportedProtocols": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The supported protocols of the rule." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "route/main.bicep" + } + } + } + }, "parameters": { "name": { "type": "string", @@ -1840,6 +3218,9 @@ }, "routes": { "type": "array", + "items": { + "$ref": "#/definitions/routeType" + }, "nullable": true, "metadata": { "description": "Optional. The list of routes for this AFD Endpoint." @@ -1862,10 +3243,7 @@ "properties": { "autoGeneratedDomainNameLabelScope": "[parameters('autoGeneratedDomainNameLabelScope')]", "enabledState": "[parameters('enabledState')]" - }, - "dependsOn": [ - "profile" - ] + } }, "afdEndpoint_routes": { "copy": { @@ -1931,13 +3309,175 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "1034122698174669197" + "version": "0.31.34.60546", + "templateHash": "15873678240851060540" }, "name": "CDN Profiles AFD Endpoint Route", "description": "This module deploys a CDN Profile AFD Endpoint route.", "owner": "Azure/module-maintainers" }, + "definitions": { + "routeType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the route." + } + }, + "cacheConfiguration": { + "$ref": "#/definitions/afdRoutecacheConfigurationType", + "nullable": true, + "metadata": { + "description": "Optional. The caching configuration for this route. To disable caching, do not provide a cacheConfiguration object." + } + }, + "customDomainNames": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the custom domains." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable use of this rule." + } + }, + "forwardingProtocol": { + "type": "string", + "allowedValues": [ + "HttpOnly", + "HttpsOnly", + "MatchRequest" + ], + "nullable": true, + "metadata": { + "description": "Optional. The protocol this rule will use when forwarding traffic to backends." + } + }, + "httpsRedirect": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to automatically redirect HTTP traffic to HTTPS traffic." + } + }, + "linkToDefaultDomain": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether this route will be linked to the default endpoint domain." + } + }, + "originGroupName": { + "type": "string", + "metadata": { + "description": "Required. The name of the origin group." + } + }, + "originPath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A directory path on the origin that AzureFrontDoor can use to retrieve content from, e.g. contoso.cloudapp.net/originpath." + } + }, + "patternsToMatch": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The route patterns of the rule." + } + }, + "ruleSets": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "metadata": { + "description": "Optional. The rule sets of the rule." + } + }, + "supportedProtocols": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The supported protocols of the rule." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "afdRoutecacheConfigurationType": { + "type": "object", + "properties": { + "compressionSettings": { + "type": "object", + "properties": { + "contentTypesToCompress": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. List of content types on which compression applies. The value should be a valid MIME type." + } + }, + "iscontentTypeToCompressAll": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicates whether content compression is enabled on AzureFrontDoor. Default value is false. If compression is enabled, content will be served as compressed if user requests for a compressed version. Content won't be compressed on AzureFrontDoor when requested content is smaller than 1 byte or larger than 1 MB." + } + } + }, + "metadata": { + "description": "Required. Compression settings." + } + }, + "queryParameters": { + "type": "string", + "metadata": { + "description": "Required. Query parameters to include or exclude (comma separated)." + } + }, + "queryStringCachingBehavior": { + "type": "string", + "allowedValues": [ + "IgnoreQueryString", + "IgnoreSpecifiedQueryStrings", + "IncludeSpecifiedQueryStrings", + "UseQueryString" + ], + "metadata": { + "description": "Required. Defines how Frontdoor caches requests that include query strings." + } + } + } + } + }, "parameters": { "name": { "type": "string", @@ -2063,10 +3603,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/afdEndpoints", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('afdEndpointName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('afdEndpointName'))]" }, "profile::customDomains": { "copy": { @@ -2076,19 +3613,13 @@ "existing": true, "type": "Microsoft.Cdn/profiles/customDomains", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), coalesce(parameters('customDomainNames'), createArray())[copyIndex()])]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), coalesce(parameters('customDomainNames'), createArray())[copyIndex()])]" }, "profile::originGroup": { "existing": true, "type": "Microsoft.Cdn/profiles/originGroups", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]" }, "profile::ruleSet": { "copy": { @@ -2098,10 +3629,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/ruleSets", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSets')[copyIndex()].name)]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSets')[copyIndex()].name)]" }, "profile": { "existing": true, @@ -2141,10 +3669,7 @@ "originPath": "[parameters('originPath')]", "patternsToMatch": "[parameters('patternsToMatch')]", "supportedProtocols": "[parameters('supportedProtocols')]" - }, - "dependsOn": [ - "profile::afdEndpoint" - ] + } } }, "outputs": { @@ -2173,8 +3698,7 @@ } }, "dependsOn": [ - "afdEndpoint", - "profile" + "afdEndpoint" ] } }, @@ -2258,8 +3782,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11561080659040848436" + "version": "0.31.34.60546", + "templateHash": "3914917842985483427" }, "name": "CDN Profiles Security Policy", "description": "This module deploys a CDN Profile Security Policy.", @@ -2349,10 +3873,7 @@ }, "associations": "[parameters('associations')]" } - }, - "dependsOn": [ - "profile" - ] + } } }, "outputs": { diff --git a/avm/res/cdn/profile/origingroup/main.bicep b/avm/res/cdn/profile/origingroup/main.bicep index 258f75686f..f404a050eb 100644 --- a/avm/res/cdn/profile/origingroup/main.bicep +++ b/avm/res/cdn/profile/origingroup/main.bicep @@ -73,3 +73,56 @@ output resourceGroupName string = resourceGroup().name @description('The location the resource was deployed into.') output location string = profile.location + +// =============== // +// Definitions // +// =============== // + +import { originType } from './origin/main.bicep' +@export() +type originGroupType = { + @description('Required. The name of the origin group.') + name: string + + @description('Required. Load balancing settings for a backend pool.') + loadBalancingSettings: loadBalancingSettingsType + + @description('Optional. Health probe settings to the origin that is used to determine the health of the origin.') + healthProbeSettings: healthProbeSettingsType? + + @description('Optional. Whether to allow session affinity on this host.') + sessionAffinityState: 'Enabled' | 'Disabled' | null + + @description('Optional. Time in minutes to shift the traffic to the endpoint gradually when an unhealthy endpoint comes healthy or a new endpoint is added. Default is 10 mins.') + trafficRestorationTimeToHealedOrNewEndpointsInMinutes: int? + + @description('Required. The list of origins within the origin group.') + origins: originType[] +} + +@export() +type loadBalancingSettingsType = { + @description('Required. Additional latency in milliseconds for probes to the backend. Must be between 0 and 1000.') + additionalLatencyInMilliseconds: int + + @description('Required. Number of samples to consider for load balancing decisions.') + sampleSize: int + + @description('Required. Number of samples within the sample window that must be successful to mark the backend as healthy.') + successfulSamplesRequired: int +} + +@export() +type healthProbeSettingsType = { + @description('Optional. The path relative to the origin that is used to determine the health of the origin.') + probePath: string? + + @description('Optional. Protocol to use for health probe.') + probeProtocol: 'Http' | 'Https' | 'NotSet' | null + + @description('Optional. The request type to probe.') + probeRequestType: 'GET' | 'HEAD' | 'NotSet' | null + + @description('Optional. The number of seconds between health probes.Default is 240sec.') + probeIntervalInSeconds: int? +} diff --git a/avm/res/cdn/profile/origingroup/main.json b/avm/res/cdn/profile/origingroup/main.json index af9a692a27..7dd74caff6 100644 --- a/avm/res/cdn/profile/origingroup/main.json +++ b/avm/res/cdn/profile/origingroup/main.json @@ -5,13 +5,223 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "16948516107556143812" + "version": "0.31.34.60546", + "templateHash": "15886213526918072525" }, "name": "CDN Profiles Origin Group", "description": "This module deploys a CDN Profile Origin Group.", "owner": "Azure/module-maintainers" }, + "definitions": { + "originGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origin group." + } + }, + "loadBalancingSettings": { + "$ref": "#/definitions/loadBalancingSettingsType", + "metadata": { + "description": "Required. Load balancing settings for a backend pool." + } + }, + "healthProbeSettings": { + "$ref": "#/definitions/healthProbeSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. Health probe settings to the origin that is used to determine the health of the origin." + } + }, + "sessionAffinityState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to allow session affinity on this host." + } + }, + "trafficRestorationTimeToHealedOrNewEndpointsInMinutes": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Time in minutes to shift the traffic to the endpoint gradually when an unhealthy endpoint comes healthy or a new endpoint is added. Default is 10 mins." + } + }, + "origins": { + "type": "array", + "items": { + "$ref": "#/definitions/originType" + }, + "metadata": { + "description": "Required. The list of origins within the origin group." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "loadBalancingSettingsType": { + "type": "object", + "properties": { + "additionalLatencyInMilliseconds": { + "type": "int", + "metadata": { + "description": "Required. Additional latency in milliseconds for probes to the backend. Must be between 0 and 1000." + } + }, + "sampleSize": { + "type": "int", + "metadata": { + "description": "Required. Number of samples to consider for load balancing decisions." + } + }, + "successfulSamplesRequired": { + "type": "int", + "metadata": { + "description": "Required. Number of samples within the sample window that must be successful to mark the backend as healthy." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "healthProbeSettingsType": { + "type": "object", + "properties": { + "probePath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The path relative to the origin that is used to determine the health of the origin." + } + }, + "probeProtocol": { + "type": "string", + "allowedValues": [ + "Http", + "Https", + "NotSet" + ], + "nullable": true, + "metadata": { + "description": "Optional. Protocol to use for health probe." + } + }, + "probeRequestType": { + "type": "string", + "allowedValues": [ + "GET", + "HEAD", + "NotSet" + ], + "nullable": true, + "metadata": { + "description": "Optional. The request type to probe." + } + }, + "probeIntervalInSeconds": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The number of seconds between health probes.Default is 240sec." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "originType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origion." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool." + } + }, + "enforceCertificateNameCheck": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable certificate name check at origin level." + } + }, + "httpPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTP port. Must be between 1 and 65535." + } + }, + "httpsPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTPS port. Must be between 1 and 65535." + } + }, + "originHostHeader": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint." + } + }, + "priority": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5." + } + }, + "weight": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Weight of the origin in given origin group for load balancing. Must be between 1 and 1000." + } + }, + "sharedPrivateLinkResource": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The properties of the private link resource for private origin." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "origin/main.bicep" + } + } + } + }, "parameters": { "name": { "type": "string", @@ -79,10 +289,7 @@ "loadBalancingSettings": "[parameters('loadBalancingSettings')]", "sessionAffinityState": "[parameters('sessionAffinityState')]", "trafficRestorationTimeToHealedOrNewEndpointsInMinutes": "[parameters('trafficRestorationTimeToHealedOrNewEndpointsInMinutes')]" - }, - "dependsOn": [ - "profile" - ] + } }, "originGroup_origins": { "copy": { @@ -142,13 +349,95 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4669077701065465911" + "version": "0.31.34.60546", + "templateHash": "3615112055594041997" }, "name": "CDN Profiles Origin", "description": "This module deploys a CDN Profile Origin.", "owner": "Azure/module-maintainers" }, + "definitions": { + "originType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origion." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool." + } + }, + "enforceCertificateNameCheck": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable certificate name check at origin level." + } + }, + "httpPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTP port. Must be between 1 and 65535." + } + }, + "httpsPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTPS port. Must be between 1 and 65535." + } + }, + "originHostHeader": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint." + } + }, + "priority": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5." + } + }, + "weight": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Weight of the origin in given origin group for load balancing. Must be between 1 and 1000." + } + }, + "sharedPrivateLinkResource": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The properties of the private link resource for private origin." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -240,10 +529,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/originGroups", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]" }, "profile": { "existing": true, @@ -265,10 +551,7 @@ "priority": "[parameters('priority')]", "sharedPrivateLinkResource": "[parameters('sharedPrivateLinkResource')]", "weight": "[parameters('weight')]" - }, - "dependsOn": [ - "profile::originGroup" - ] + } } }, "outputs": { diff --git a/avm/res/cdn/profile/origingroup/origin/main.bicep b/avm/res/cdn/profile/origingroup/origin/main.bicep index ccf7a62aa1..166e2b43ac 100644 --- a/avm/res/cdn/profile/origingroup/origin/main.bicep +++ b/avm/res/cdn/profile/origingroup/origin/main.bicep @@ -74,3 +74,40 @@ output resourceId string = origin.id @description('The name of the resource group the origin was created in.') output resourceGroupName string = resourceGroup().name + +// =============== // +// Definitions // +// =============== // + +@export() +type originType = { + @description('Required. The name of the origion.') + name: string + + @description('Required. The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint.') + hostName: string + + @description('Optional. Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool.') + enabledState: 'Enabled' | 'Disabled' | null + + @description('Optional. Whether to enable certificate name check at origin level.') + enforceCertificateNameCheck: bool? + + @description('Optional. The value of the HTTP port. Must be between 1 and 65535.') + httpPort: int? + + @description('Optional. The value of the HTTPS port. Must be between 1 and 65535.') + httpsPort: int? + + @description('Optional. The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint.') + originHostHeader: string? + + @description('Optional. Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5.') + priority: int? + + @description('Optional. Weight of the origin in given origin group for load balancing. Must be between 1 and 1000.') + weight: int? + + @description('Optional. The properties of the private link resource for private origin.') + sharedPrivateLinkResource: object? +} diff --git a/avm/res/cdn/profile/origingroup/origin/main.json b/avm/res/cdn/profile/origingroup/origin/main.json index 8ee5bf04df..6488e9907f 100644 --- a/avm/res/cdn/profile/origingroup/origin/main.json +++ b/avm/res/cdn/profile/origingroup/origin/main.json @@ -5,13 +5,95 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4669077701065465911" + "version": "0.31.34.60546", + "templateHash": "3615112055594041997" }, "name": "CDN Profiles Origin", "description": "This module deploys a CDN Profile Origin.", "owner": "Azure/module-maintainers" }, + "definitions": { + "originType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the origion." + } + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Required. The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported.This should be unique across all origins in an endpoint." + } + }, + "enabledState": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable health probes to be made against backends defined under backendPools. Health probes can only be disabled if there is a single enabled backend in single enabled backend pool." + } + }, + "enforceCertificateNameCheck": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to enable certificate name check at origin level." + } + }, + "httpPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTP port. Must be between 1 and 65535." + } + }, + "httpsPort": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The value of the HTTPS port. Must be between 1 and 65535." + } + }, + "originHostHeader": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint." + } + }, + "priority": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any lower priority origin is healthy.Must be between 1 and 5." + } + }, + "weight": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Weight of the origin in given origin group for load balancing. Must be between 1 and 1000." + } + }, + "sharedPrivateLinkResource": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The properties of the private link resource for private origin." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -103,10 +185,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/originGroups", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('originGroupName'))]" }, "profile": { "existing": true, @@ -128,10 +207,7 @@ "priority": "[parameters('priority')]", "sharedPrivateLinkResource": "[parameters('sharedPrivateLinkResource')]", "weight": "[parameters('weight')]" - }, - "dependsOn": [ - "profile::originGroup" - ] + } } }, "outputs": { diff --git a/avm/res/cdn/profile/ruleset/main.bicep b/avm/res/cdn/profile/ruleset/main.bicep index 9d96381236..dbaf29f99c 100644 --- a/avm/res/cdn/profile/ruleset/main.bicep +++ b/avm/res/cdn/profile/ruleset/main.bicep @@ -9,7 +9,7 @@ param name string param profileName string @description('Optinal. The rules to apply to the rule set.') -param rules array? +param rules ruleType[]? resource profile 'Microsoft.Cdn/profiles@2023-05-01' existing = { name: profileName @@ -35,6 +35,17 @@ module ruleSet_rules 'rule/main.bicep' = [ } ] +import { ruleType } from './rule/main.bicep' + +@export() +type ruleSetType = { + @description('Required. Name of the rule set.') + name: string + + @description('Optional. Array of rules.') + rules: ruleType[]? +} + @description('The name of the rule set.') output name string = ruleSet.name diff --git a/avm/res/cdn/profile/ruleset/main.json b/avm/res/cdn/profile/ruleset/main.json index 2d040690b5..cffc63c7ee 100644 --- a/avm/res/cdn/profile/ruleset/main.json +++ b/avm/res/cdn/profile/ruleset/main.json @@ -5,13 +5,86 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11520922481694023973" + "version": "0.31.34.60546", + "templateHash": "4753233857701337613" }, "name": "CDN Profiles Rule Sets", "description": "This module deploys a CDN Profile rule set.", "owner": "Azure/module-maintainers" }, + "definitions": { + "ruleSetType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the rule set." + } + }, + "rules": { + "type": "array", + "items": { + "$ref": "#/definitions/ruleType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of rules." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "ruleType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the rule." + } + }, + "order": { + "type": "int", + "metadata": { + "description": "Required. The order in which the rules are applied for the endpoint." + } + }, + "actions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of actions that are executed when all the conditions of a rule are satisfied.." + } + }, + "conditions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of conditions that must be matched for the actions to be executed." + } + }, + "matchProcessingBehavior": { + "type": "string", + "allowedValues": [ + "Continue", + "Stop" + ], + "nullable": true, + "metadata": { + "description": "Optional. If this rule is a match should the rules engine continue running the remaining rules or stop. If not present, defaults to Continue." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "rule/main.bicep" + } + } + } + }, "parameters": { "name": { "type": "string", @@ -27,6 +100,9 @@ }, "rules": { "type": "array", + "items": { + "$ref": "#/definitions/ruleType" + }, "nullable": true, "metadata": { "description": "Optinal. The rules to apply to the rule set." @@ -43,10 +119,7 @@ "ruleSet": { "type": "Microsoft.Cdn/profiles/ruleSets", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('name'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('name'))]" }, "ruleSet_rules": { "copy": { @@ -91,13 +164,60 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "8818585542646204223" + "version": "0.31.34.60546", + "templateHash": "11756620080021514486" }, "name": "CDN Profiles Rules", "description": "This module deploys a CDN Profile rule.", "owner": "Azure/module-maintainers" }, + "definitions": { + "ruleType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the rule." + } + }, + "order": { + "type": "int", + "metadata": { + "description": "Required. The order in which the rules are applied for the endpoint." + } + }, + "actions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of actions that are executed when all the conditions of a rule are satisfied.." + } + }, + "conditions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of conditions that must be matched for the actions to be executed." + } + }, + "matchProcessingBehavior": { + "type": "string", + "allowedValues": [ + "Continue", + "Stop" + ], + "nullable": true, + "metadata": { + "description": "Optional. If this rule is a match should the rules engine continue running the remaining rules or stop. If not present, defaults to Continue." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -154,10 +274,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/ruleSets", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSetName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSetName'))]" }, "profile": { "existing": true, @@ -174,10 +291,7 @@ "actions": "[parameters('actions')]", "conditions": "[parameters('conditions')]", "matchProcessingBehavior": "[parameters('matchProcessingBehavior')]" - }, - "dependsOn": [ - "profile::ruleSet" - ] + } } }, "outputs": { diff --git a/avm/res/cdn/profile/ruleset/rule/main.bicep b/avm/res/cdn/profile/ruleset/rule/main.bicep index 7851860264..2f172c93ce 100644 --- a/avm/res/cdn/profile/ruleset/rule/main.bicep +++ b/avm/res/cdn/profile/ruleset/rule/main.bicep @@ -54,3 +54,21 @@ output resourceId string = rule.id @description('The name of the resource group the custom domain was created in.') output resourceGroupName string = resourceGroup().name + +@export() +type ruleType = { + @description('Required. The name of the rule.') + name: string + + @description('Required. The order in which the rules are applied for the endpoint.') + order: int + + @description('Optional. A list of actions that are executed when all the conditions of a rule are satisfied..') + actions: array? + + @description('Optional. A list of conditions that must be matched for the actions to be executed.') + conditions: array? + + @description('Optional. If this rule is a match should the rules engine continue running the remaining rules or stop. If not present, defaults to Continue.') + matchProcessingBehavior: 'Continue' | 'Stop' | null +} diff --git a/avm/res/cdn/profile/ruleset/rule/main.json b/avm/res/cdn/profile/ruleset/rule/main.json index 98e0f0fef8..465bed9ee5 100644 --- a/avm/res/cdn/profile/ruleset/rule/main.json +++ b/avm/res/cdn/profile/ruleset/rule/main.json @@ -5,13 +5,60 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "8818585542646204223" + "version": "0.31.34.60546", + "templateHash": "11756620080021514486" }, "name": "CDN Profiles Rules", "description": "This module deploys a CDN Profile rule.", "owner": "Azure/module-maintainers" }, + "definitions": { + "ruleType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the rule." + } + }, + "order": { + "type": "int", + "metadata": { + "description": "Required. The order in which the rules are applied for the endpoint." + } + }, + "actions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of actions that are executed when all the conditions of a rule are satisfied.." + } + }, + "conditions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of conditions that must be matched for the actions to be executed." + } + }, + "matchProcessingBehavior": { + "type": "string", + "allowedValues": [ + "Continue", + "Stop" + ], + "nullable": true, + "metadata": { + "description": "Optional. If this rule is a match should the rules engine continue running the remaining rules or stop. If not present, defaults to Continue." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -68,10 +115,7 @@ "existing": true, "type": "Microsoft.Cdn/profiles/ruleSets", "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSetName'))]", - "dependsOn": [ - "profile" - ] + "name": "[format('{0}/{1}', parameters('profileName'), parameters('ruleSetName'))]" }, "profile": { "existing": true, @@ -88,10 +132,7 @@ "actions": "[parameters('actions')]", "conditions": "[parameters('conditions')]", "matchProcessingBehavior": "[parameters('matchProcessingBehavior')]" - }, - "dependsOn": [ - "profile::ruleSet" - ] + } } }, "outputs": { diff --git a/avm/res/cdn/profile/secret/README.md b/avm/res/cdn/profile/secret/README.md index e599331771..b3048b8a2a 100644 --- a/avm/res/cdn/profile/secret/README.md +++ b/avm/res/cdn/profile/secret/README.md @@ -21,7 +21,6 @@ This module deploys a CDN Profile Secret. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | The name of the secrect. | -| [`type`](#parameter-type) | string | The type of the secrect. | **Conditional parameters** @@ -36,6 +35,7 @@ This module deploys a CDN Profile Secret. | :-- | :-- | :-- | | [`secretVersion`](#parameter-secretversion) | string | The version of the secret. | | [`subjectAlternativeNames`](#parameter-subjectalternativenames) | array | The subject alternative names of the secrect. | +| [`type`](#parameter-type) | string | The type of the secrect. | | [`useLatestVersion`](#parameter-uselatestversion) | bool | Indicates whether to use the latest version of the secrect. | ### Parameter: `name` @@ -45,23 +45,6 @@ The name of the secrect. - Required: Yes - Type: string -### Parameter: `type` - -The type of the secrect. - -- Required: No -- Type: string -- Default: `'AzureFirstPartyManagedCertificate'` -- Allowed: - ```Bicep - [ - 'AzureFirstPartyManagedCertificate' - 'CustomerCertificate' - 'ManagedCertificate' - 'UrlSigningKey' - ] - ``` - ### Parameter: `profileName` The name of the parent CDN profile. Required if the template is used in a standalone deployment. @@ -93,6 +76,23 @@ The subject alternative names of the secrect. - Type: array - Default: `[]` +### Parameter: `type` + +The type of the secrect. + +- Required: No +- Type: string +- Default: `'AzureFirstPartyManagedCertificate'` +- Allowed: + ```Bicep + [ + 'AzureFirstPartyManagedCertificate' + 'CustomerCertificate' + 'ManagedCertificate' + 'UrlSigningKey' + ] + ``` + ### Parameter: `useLatestVersion` Indicates whether to use the latest version of the secrect. diff --git a/avm/res/cdn/profile/secret/main.bicep b/avm/res/cdn/profile/secret/main.bicep index e4278f4057..064586b436 100644 --- a/avm/res/cdn/profile/secret/main.bicep +++ b/avm/res/cdn/profile/secret/main.bicep @@ -14,7 +14,7 @@ param profileName string 'ManagedCertificate' 'UrlSigningKey' ]) -@description('Required. The type of the secrect.') +@description('Optional. The type of the secrect.') param type string = 'AzureFirstPartyManagedCertificate' @description('Conditional. The resource ID of the secret source. Required if the `type` is "CustomerCertificate".') diff --git a/avm/res/cdn/profile/secret/main.json b/avm/res/cdn/profile/secret/main.json index 6c300587db..4c2f0abd3c 100644 --- a/avm/res/cdn/profile/secret/main.json +++ b/avm/res/cdn/profile/secret/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "7661706938502506866" + "version": "0.31.34.60546", + "templateHash": "135211401759640973" }, "name": "CDN Profiles Secret", "description": "This module deploys a CDN Profile Secret.", @@ -34,7 +34,7 @@ "UrlSigningKey" ], "metadata": { - "description": "Required. The type of the secrect." + "description": "Optional. The type of the secrect." } }, "secretSourceResourceId": { diff --git a/avm/res/cdn/profile/securityPolicies/main.json b/avm/res/cdn/profile/securityPolicies/main.json index be06e14c99..e94a644cf3 100644 --- a/avm/res/cdn/profile/securityPolicies/main.json +++ b/avm/res/cdn/profile/securityPolicies/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11561080659040848436" + "version": "0.31.34.60546", + "templateHash": "3914917842985483427" }, "name": "CDN Profiles Security Policy", "description": "This module deploys a CDN Profile Security Policy.", @@ -96,10 +96,7 @@ }, "associations": "[parameters('associations')]" } - }, - "dependsOn": [ - "profile" - ] + } } }, "outputs": { diff --git a/avm/res/cdn/profile/version.json b/avm/res/cdn/profile/version.json index 35040975ae..0f81d22abc 100644 --- a/avm/res/cdn/profile/version.json +++ b/avm/res/cdn/profile/version.json @@ -1,7 +1,7 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.7", + "version": "0.8", "pathFilters": [ "./main.json" ] -} +} \ No newline at end of file diff --git a/avm/res/cognitive-services/account/README.md b/avm/res/cognitive-services/account/README.md index c4316e2e52..3cc1613e68 100644 --- a/avm/res/cognitive-services/account/README.md +++ b/avm/res/cognitive-services/account/README.md @@ -2260,15 +2260,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -2277,6 +2275,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/cognitive-services/account/main.bicep b/avm/res/cognitive-services/account/main.bicep index e7d426a344..f8378c75fa 100644 --- a/avm/res/cognitive-services/account/main.bicep +++ b/avm/res/cognitive-services/account/main.bicep @@ -652,7 +652,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/cognitive-services/account/main.json b/avm/res/cognitive-services/account/main.json index c2ce82cbd8..1d4e6730fc 100644 --- a/avm/res/cognitive-services/account/main.json +++ b/avm/res/cognitive-services/account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "11788701359615687264" + "templateHash": "10707676565122599824" }, "name": "Cognitive Services", "description": "This module deploys a Cognitive Service.", @@ -309,7 +309,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { diff --git a/avm/res/compute/virtual-machine/README.md b/avm/res/compute/virtual-machine/README.md index 16a4e92bf0..3fd239938e 100644 --- a/avm/res/compute/virtual-machine/README.md +++ b/avm/res/compute/virtual-machine/README.md @@ -19,6 +19,7 @@ This module deploys a Virtual Machine with one or multiple NICs and optionally o | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Automanage/configurationProfileAssignments` | [2022-05-04](https://learn.microsoft.com/en-us/azure/templates) | +| `Microsoft.Compute/disks` | [2024-03-02](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2024-03-02/disks) | | `Microsoft.Compute/virtualMachines` | [2024-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2024-07-01/virtualMachines) | | `Microsoft.Compute/virtualMachines/extensions` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachines/extensions) | | `Microsoft.DevTestLab/schedules` | [2018-09-15](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DevTestLab/2018-09-15/schedules) | @@ -47,8 +48,9 @@ The following section provides usage examples for the module, which were used to - [Using a host pool to register the VM](#example-7-using-a-host-pool-to-register-the-vm) - [Using large parameter set for Windows](#example-8-using-large-parameter-set-for-windows) - [Deploy a VM with nVidia graphic card](#example-9-deploy-a-vm-with-nvidia-graphic-card) -- [Using disk encryption set for the VM.](#example-10-using-disk-encryption-set-for-the-vm) -- [Adding the VM to a VMSS.](#example-11-adding-the-vm-to-a-vmss) +- [Deploying Windows VM with premium SSDv2 data disk](#example-10-deploying-windows-vm-with-premium-ssdv2-data-disk) +- [Using disk encryption set for the VM.](#example-11-using-disk-encryption-set-for-the-vm) +- [Adding the VM to a VMSS.](#example-12-adding-the-vm-to-a-vmss) ### Example 1: _Using automanage for the VM._ @@ -4152,7 +4154,209 @@ param location = ''

    -### Example 10: _Using disk encryption set for the VM._ +### Example 10: _Deploying Windows VM with premium SSDv2 data disk_ + +This instance deploys the module with premium SSDv2 data disk. + + +

    + +via Bicep module + +```bicep +module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { + name: 'virtualMachineDeployment' + params: { + // Required parameters + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + name: 'cvmwinssdv2' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: '' + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + caching: 'ReadWrite' + diskSizeGB: 128 + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_D2s_v3' + zone: 1 + // Non-required parameters + adminPassword: '' + dataDisks: [ + { + caching: 'None' + diskIOPSReadWrite: 3000 + diskMBpsReadWrite: 125 + diskSizeGB: 1024 + managedDisk: { + storageAccountType: 'PremiumV2_LRS' + } + } + ] + location: '' + } +} +``` + +
    +

    + +

    + +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "localAdminUser" + }, + "imageReference": { + "value": { + "offer": "WindowsServer", + "publisher": "MicrosoftWindowsServer", + "sku": "2022-datacenter-azure-edition", + "version": "latest" + } + }, + "name": { + "value": "cvmwinssdv2" + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetResourceId": "" + } + ], + "nicSuffix": "-nic-01" + } + ] + }, + "osDisk": { + "value": { + "caching": "ReadWrite", + "diskSizeGB": 128, + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_D2s_v3" + }, + "zone": { + "value": 1 + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "dataDisks": { + "value": [ + { + "caching": "None", + "diskIOPSReadWrite": 3000, + "diskMBpsReadWrite": 125, + "diskSizeGB": 1024, + "managedDisk": { + "storageAccountType": "PremiumV2_LRS" + } + } + ] + }, + "location": { + "value": "" + } + } +} +``` + +
    +

    + +

    + +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/compute/virtual-machine:' + +// Required parameters +param adminUsername = 'localAdminUser' +param imageReference = { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' +} +param name = 'cvmwinssdv2' +param nicConfigurations = [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: '' + } + ] + nicSuffix: '-nic-01' + } +] +param osDisk = { + caching: 'ReadWrite' + diskSizeGB: 128 + managedDisk: { + storageAccountType: 'Premium_LRS' + } +} +param osType = 'Windows' +param vmSize = 'Standard_D2s_v3' +param zone = 1 +// Non-required parameters +param adminPassword = '' +param dataDisks = [ + { + caching: 'None' + diskIOPSReadWrite: 3000 + diskMBpsReadWrite: 125 + diskSizeGB: 1024 + managedDisk: { + storageAccountType: 'PremiumV2_LRS' + } + } +] +param location = '' +``` + +
    +

    + +### Example 11: _Using disk encryption set for the VM._ This instance deploys the module with disk enryption set. @@ -4360,7 +4564,7 @@ param location = ''

    -### Example 11: _Adding the VM to a VMSS._ +### Example 12: _Adding the VM to a VMSS._ This instance deploys the module with the minimum set of required parameters and adds it to a VMSS. @@ -4613,6 +4817,7 @@ param virtualMachineScaleSetResourceId = '' | [`tags`](#parameter-tags) | object | Tags of the resource. | | [`timeZone`](#parameter-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`](#parameter-ultrassdenabled) | bool | 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. | +| [`userData`](#parameter-userdata) | string | UserData for the VM, which must be base-64 encoded. Customer should not pass any secrets in here. | | [`virtualMachineScaleSetResourceId`](#parameter-virtualmachinescalesetresourceid) | string | Resource ID of a virtual machine scale set, where the VM should be added. | | [`vTpmEnabled`](#parameter-vtpmenabled) | bool | 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`](#parameter-winrm) | array | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | @@ -4958,6 +5163,8 @@ Specifies the data disks. For security reasons, it is recommended to specify Dis | [`caching`](#parameter-datadiskscaching) | string | Specifies the caching requirements. | | [`createOption`](#parameter-datadiskscreateoption) | string | Specifies how the virtual machine should be created. | | [`deleteOption`](#parameter-datadisksdeleteoption) | string | Specifies whether data disk should be deleted or detached upon VM deletion. | +| [`diskIOPSReadWrite`](#parameter-datadisksdiskiopsreadwrite) | int | The number of IOPS allowed for this disk; only settable for UltraSSD disks. One operation can transfer between 4k and 256k bytes. | +| [`diskMBpsReadWrite`](#parameter-datadisksdiskmbpsreadwrite) | int | The bandwidth allowed for this disk; only settable for UltraSSD disks. MBps means millions of bytes per second - MB here uses the ISO notation, of powers of 10. | | [`lun`](#parameter-datadiskslun) | int | Specifies the logical unit number of the data disk. | | [`name`](#parameter-datadisksname) | string | The disk name. | @@ -4986,6 +5193,7 @@ The managed disk parameters. | Parameter | Type | Description | | :-- | :-- | :-- | | [`diskEncryptionSetResourceId`](#parameter-datadisksmanageddiskdiskencryptionsetresourceid) | string | Specifies the customer managed disk encryption set resource id for the managed disk. | +| [`id`](#parameter-datadisksmanageddiskid) | string | Specifies the customer managed disk id for the managed disk. | ### Parameter: `dataDisks.managedDisk.storageAccountType` @@ -5013,6 +5221,13 @@ Specifies the customer managed disk encryption set resource id for the managed d - Required: No - Type: string +### Parameter: `dataDisks.managedDisk.id` + +Specifies the customer managed disk id for the managed disk. + +- Required: No +- Type: string + ### Parameter: `dataDisks.caching` Specifies the caching requirements. @@ -5057,6 +5272,20 @@ Specifies whether data disk should be deleted or detached upon VM deletion. ] ``` +### Parameter: `dataDisks.diskIOPSReadWrite` + +The number of IOPS allowed for this disk; only settable for UltraSSD disks. One operation can transfer between 4k and 256k bytes. + +- Required: No +- Type: int + +### Parameter: `dataDisks.diskMBpsReadWrite` + +The bandwidth allowed for this disk; only settable for UltraSSD disks. MBps means millions of bytes per second - MB here uses the ISO notation, of powers of 10. + +- Required: No +- Type: int + ### Parameter: `dataDisks.lun` Specifies the logical unit number of the data disk. @@ -5695,6 +5924,14 @@ The flag that enables or disables a capability to have one or more managed data - Type: bool - Default: `False` +### Parameter: `userData` + +UserData for the VM, which must be base-64 encoded. Customer should not pass any secrets in here. + +- Required: No +- Type: string +- Default: `''` + ### Parameter: `virtualMachineScaleSetResourceId` Resource ID of a virtual machine scale set, where the VM should be added. diff --git a/avm/res/compute/virtual-machine/extension/main.json b/avm/res/compute/virtual-machine/extension/main.json index 702433c26d..e42039bdd8 100644 --- a/avm/res/compute/virtual-machine/extension/main.json +++ b/avm/res/compute/virtual-machine/extension/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10657605324993327332" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -121,10 +121,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { diff --git a/avm/res/compute/virtual-machine/main.bicep b/avm/res/compute/virtual-machine/main.bicep index d9f22a1b23..27c7365be7 100644 --- a/avm/res/compute/virtual-machine/main.bicep +++ b/avm/res/compute/virtual-machine/main.bicep @@ -51,6 +51,9 @@ param adminUsername string @secure() param adminPassword string = '' +@description('Optional. UserData for the VM, which must be base-64 encoded. Customer should not pass any secrets in here.') +param userData 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 = '' @@ -497,6 +500,25 @@ module vm_nic 'modules/nic-configuration.bicep' = [ } ] +resource managedDataDisks 'Microsoft.Compute/disks@2024-03-02' = [ + for (dataDisk, index) in dataDisks ?? []: { + location: location + name: dataDisk.?name ?? '${name}-disk-data-${padLeft((index + 1), 2, '0')}' + sku: { + name: dataDisk.managedDisk.storageAccountType + } + properties: { + diskSizeGB: dataDisk.diskSizeGB + creationData: { + createOption: dataDisk.?createoption ?? 'Empty' + } + diskIOPSReadWrite: dataDisk.?diskIOPSReadWrite + diskMBpsReadWrite: dataDisk.?diskMBpsReadWrite + } + zones: zone != 0 ? array(string(zone)) : null + } +] + resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' = { name: name location: location @@ -538,11 +560,12 @@ resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' = { lun: dataDisk.?lun ?? index name: dataDisk.?name ?? '${name}-disk-data-${padLeft((index + 1), 2, '0')}' diskSizeGB: dataDisk.diskSizeGB - createOption: dataDisk.?createoption ?? 'Empty' + createOption: (managedDataDisks[index].?id != null) ? 'Attach' : dataDisk.?createoption ?? 'Empty' deleteOption: dataDisk.?deleteOption ?? 'Delete' caching: dataDisk.?caching ?? 'ReadOnly' managedDisk: { storageAccountType: dataDisk.managedDisk.storageAccountType + id: managedDataDisks[index].?id diskEncryptionSet: { id: dataDisk.managedDisk.?diskEncryptionSetResourceId } @@ -620,6 +643,7 @@ resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' = { } : null licenseType: !empty(licenseType) ? licenseType : null + userData: !empty(userData) ? base64(userData) : null } dependsOn: [ vm_nic @@ -1107,6 +1131,12 @@ type dataDisksType = { @description('Optional. Specifies the caching requirements.') caching: 'None' | 'ReadOnly' | 'ReadWrite'? + @description('Optional. The number of IOPS allowed for this disk; only settable for UltraSSD disks. One operation can transfer between 4k and 256k bytes.') + diskIOPSReadWrite: int? + + @description('Optional. The bandwidth allowed for this disk; only settable for UltraSSD disks. MBps means millions of bytes per second - MB here uses the ISO notation, of powers of 10.') + diskMBpsReadWrite: int? + @description('Required. The managed disk parameters.') managedDisk: { @description('Required. Specifies the storage account type for the managed disk.') @@ -1121,5 +1151,8 @@ type dataDisksType = { @description('Optional. Specifies the customer managed disk encryption set resource id for the managed disk.') diskEncryptionSetResourceId: string? + + @description('Optional. Specifies the customer managed disk id for the managed disk.') + id: string? } }[]? diff --git a/avm/res/compute/virtual-machine/main.json b/avm/res/compute/virtual-machine/main.json index de1432dd89..ee412188a1 100644 --- a/avm/res/compute/virtual-machine/main.json +++ b/avm/res/compute/virtual-machine/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1443306495474212036" + "version": "0.31.34.60546", + "templateHash": "8773273774920281983" }, "name": "Virtual Machines", "description": "This module deploys a Virtual Machine with one or multiple NICs and optionally one or multiple public IPs.", @@ -279,6 +279,20 @@ "description": "Optional. Specifies the caching requirements." } }, + "diskIOPSReadWrite": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The number of IOPS allowed for this disk; only settable for UltraSSD disks. One operation can transfer between 4k and 256k bytes." + } + }, + "diskMBpsReadWrite": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The bandwidth allowed for this disk; only settable for UltraSSD disks. MBps means millions of bytes per second - MB here uses the ISO notation, of powers of 10." + } + }, "managedDisk": { "type": "object", "properties": { @@ -303,6 +317,13 @@ "metadata": { "description": "Optional. Specifies the customer managed disk encryption set resource id for the managed disk." } + }, + "id": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specifies the customer managed disk id for the managed disk." + } } }, "metadata": { @@ -412,6 +433,13 @@ "description": "Optional. When specifying a Windows Virtual Machine, this value should be passed." } }, + "userData": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. UserData for the VM, which must be base-64 encoded. Customer should not pass any secrets in here." + } + }, "customData": { "type": "string", "defaultValue": "", @@ -973,6 +1001,28 @@ } } }, + "managedDataDisks": { + "copy": { + "name": "managedDataDisks", + "count": "[length(coalesce(parameters('dataDisks'), createArray()))]" + }, + "type": "Microsoft.Compute/disks", + "apiVersion": "2024-03-02", + "name": "[coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex()], 'name'), format('{0}-disk-data-{1}', parameters('name'), padLeft(add(copyIndex(), 1), 2, '0')))]", + "location": "[parameters('location')]", + "sku": { + "name": "[coalesce(parameters('dataDisks'), createArray())[copyIndex()].managedDisk.storageAccountType]" + }, + "properties": { + "diskSizeGB": "[coalesce(parameters('dataDisks'), createArray())[copyIndex()].diskSizeGB]", + "creationData": { + "createOption": "[coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex()], 'createoption'), 'Empty')]" + }, + "diskIOPSReadWrite": "[tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex()], 'diskIOPSReadWrite')]", + "diskMBpsReadWrite": "[tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex()], 'diskMBpsReadWrite')]" + }, + "zones": "[if(not(equals(parameters('zone'), 0)), array(string(parameters('zone'))), null())]" + }, "vm": { "type": "Microsoft.Compute/virtualMachines", "apiVersion": "2024-07-01", @@ -1000,11 +1050,12 @@ "lun": "[coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')], 'lun'), copyIndex('dataDisks'))]", "name": "[coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')], 'name'), format('{0}-disk-data-{1}', parameters('name'), padLeft(add(copyIndex('dataDisks'), 1), 2, '0')))]", "diskSizeGB": "[coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')].diskSizeGB]", - "createOption": "[coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')], 'createoption'), 'Empty')]", + "createOption": "[if(not(equals(resourceId('Microsoft.Compute/disks', coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')], 'name'), format('{0}-disk-data-{1}', parameters('name'), padLeft(add(copyIndex('dataDisks'), 1), 2, '0')))), null())), 'Attach', coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')], 'createoption'), 'Empty'))]", "deleteOption": "[coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')], 'deleteOption'), 'Delete')]", "caching": "[coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')], 'caching'), 'ReadOnly')]", "managedDisk": { "storageAccountType": "[coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')].managedDisk.storageAccountType]", + "id": "[resourceId('Microsoft.Compute/disks', coalesce(tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')], 'name'), format('{0}-disk-data-{1}', parameters('name'), padLeft(add(copyIndex('dataDisks'), 1), 2, '0'))))]", "diskEncryptionSet": { "id": "[tryGet(coalesce(parameters('dataDisks'), createArray())[copyIndex('dataDisks')].managedDisk, 'diskEncryptionSetResourceId')]" } @@ -1069,9 +1120,11 @@ "evictionPolicy": "[if(parameters('enableEvictionPolicy'), 'Deallocate', null())]", "billingProfile": "[if(and(not(empty(parameters('priority'))), not(empty(parameters('maxPriceForLowPriorityVm')))), createObject('maxPrice', json(parameters('maxPriceForLowPriorityVm'))), null())]", "host": "[if(not(empty(parameters('dedicatedHostId'))), createObject('id', parameters('dedicatedHostId')), null())]", - "licenseType": "[if(not(empty(parameters('licenseType'))), parameters('licenseType'), null())]" + "licenseType": "[if(not(empty(parameters('licenseType'))), parameters('licenseType'), null())]", + "userData": "[if(not(empty(parameters('userData'))), base64(parameters('userData')), null())]" }, "dependsOn": [ + "managedDataDisks", "vm_nic" ] }, @@ -1251,8 +1304,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "191716886366421622" + "version": "0.31.34.60546", + "templateHash": "4400762038950491974" } }, "definitions": { @@ -2855,8 +2908,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -2971,10 +3024,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -3070,8 +3120,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -3186,10 +3236,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -3281,8 +3328,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -3397,10 +3444,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -3487,8 +3531,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -3603,10 +3647,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -3698,8 +3739,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -3814,10 +3855,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -3904,8 +3942,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -4020,10 +4058,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -4118,8 +4153,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -4234,10 +4269,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -4336,8 +4368,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -4452,10 +4484,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -4548,8 +4577,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -4664,10 +4693,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -4756,8 +4782,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -4872,10 +4898,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -4973,8 +4996,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -5089,10 +5112,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -5186,8 +5206,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "1742015474710386242" + "version": "0.31.34.60546", + "templateHash": "1194243367873711347" }, "name": "Virtual Machine Extensions", "description": "This module deploys a Virtual Machine Extension.", @@ -5302,10 +5322,7 @@ "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] + } } }, "outputs": { @@ -5385,8 +5402,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "18427642917647797213" + "version": "0.31.34.60546", + "templateHash": "7575343013066166436" }, "name": "Recovery Service Vaults Protection Container Protected Item", "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.SSDv2/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.SSDv2/dependencies.bicep new file mode 100644 index 0000000000..68972ec7ec --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/windows.SSDv2/dependencies.bicep @@ -0,0 +1,30 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.SSDv2/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.SSDv2/main.test.bicep new file mode 100644 index 0000000000..d2e547f0cc --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/windows.SSDv2/main.test.bicep @@ -0,0 +1,101 @@ +targetScope = 'subscription' + +metadata name = 'Deploying Windows VM with premium SSDv2 data disk' +metadata description = 'This instance deploys the module with premium SSDv2 data disk.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' + +// Capacity constraints for VM type +#disable-next-line no-hardcoded-location +var enforcedLocation = 'uksouth' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cvmwinssdv2' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' + params: { + location: enforcedLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + location: enforcedLocation + name: '${namePrefix}${serviceShort}' + adminUsername: 'localAdminUser' + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + zone: 1 + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: 128 + caching: 'ReadWrite' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + dataDisks: [ + { + diskSizeGB: 1024 + caching: 'None' + managedDisk: { + storageAccountType: 'PremiumV2_LRS' + } + diskIOPSReadWrite: 3000 + diskMBpsReadWrite: 125 + } + ] + osType: 'Windows' + vmSize: 'Standard_D2s_v3' + adminPassword: password + } + } +] diff --git a/avm/res/compute/virtual-machine/version.json b/avm/res/compute/virtual-machine/version.json index 9a9a06e897..a830c3d961 100644 --- a/avm/res/compute/virtual-machine/version.json +++ b/avm/res/compute/virtual-machine/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.8", + "version": "0.10", "pathFilters": [ "./main.json" ] diff --git a/avm/res/consumption/budget/README.md b/avm/res/consumption/budget/README.md index a72051517a..0116781b9d 100644 --- a/avm/res/consumption/budget/README.md +++ b/avm/res/consumption/budget/README.md @@ -422,8 +422,6 @@ param thresholds = [ | :-- | :-- | :-- | | [`amount`](#parameter-amount) | int | The total amount of cost or usage to track with the budget. | | [`name`](#parameter-name) | string | The name of the budget. | -| [`operator`](#parameter-operator) | string | The comparison operator. The operator can be either `EqualTo`, `GreaterThan`, or `GreaterThanOrEqualTo`. | -| [`thresholdType`](#parameter-thresholdtype) | string | The type of threshold to use for the budget. The threshold type can be either `Actual` or `Forecasted`. | **Conditional parameters** @@ -442,10 +440,12 @@ param thresholds = [ | [`endDate`](#parameter-enddate) | string | The end date for the budget. If not provided, it will default to 10 years from the start date. | | [`filter`](#parameter-filter) | object | The filter to use for restricting which resources are considered within the budget. | | [`location`](#parameter-location) | string | Location deployment metadata. | +| [`operator`](#parameter-operator) | string | The comparison operator. The operator can be either `EqualTo`, `GreaterThan`, or `GreaterThanOrEqualTo`. | | [`resetPeriod`](#parameter-resetperiod) | string | 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. | | [`resourceGroupFilter`](#parameter-resourcegroupfilter) | array | The list of resource groups that contain the resources that are to be considered within the budget. | | [`startDate`](#parameter-startdate) | string | 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`](#parameter-thresholds) | array | Percent thresholds of budget for when to get a notification. Can be up to 5 thresholds, where each must be between 1 and 1000. | +| [`thresholdType`](#parameter-thresholdtype) | string | The type of threshold to use for the budget. The threshold type can be either `Actual` or `Forecasted`. | ### Parameter: `amount` @@ -461,37 +461,6 @@ The name of the budget. - Required: Yes - Type: string -### Parameter: `operator` - -The comparison operator. The operator can be either `EqualTo`, `GreaterThan`, or `GreaterThanOrEqualTo`. - -- Required: No -- Type: string -- Default: `'GreaterThan'` -- Allowed: - ```Bicep - [ - 'EqualTo' - 'GreaterThan' - 'GreaterThanOrEqualTo' - ] - ``` - -### Parameter: `thresholdType` - -The type of threshold to use for the budget. The threshold type can be either `Actual` or `Forecasted`. - -- Required: No -- Type: string -- Default: `'Actual'` -- Allowed: - ```Bicep - [ - 'Actual' - 'Forecasted' - ] - ``` - ### Parameter: `actionGroups` List of action group resource IDs that will receive the alert. Required if neither `contactEmails` nor `contactEmails` was provided. @@ -559,6 +528,22 @@ Location deployment metadata. - Type: string - Default: `[deployment().location]` +### Parameter: `operator` + +The comparison operator. The operator can be either `EqualTo`, `GreaterThan`, or `GreaterThanOrEqualTo`. + +- Required: No +- Type: string +- Default: `'GreaterThan'` +- Allowed: + ```Bicep + [ + 'EqualTo' + 'GreaterThan' + 'GreaterThanOrEqualTo' + ] + ``` + ### Parameter: `resetPeriod` 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. @@ -611,6 +596,21 @@ Percent thresholds of budget for when to get a notification. Can be up to 5 thre ] ``` +### Parameter: `thresholdType` + +The type of threshold to use for the budget. The threshold type can be either `Actual` or `Forecasted`. + +- Required: No +- Type: string +- Default: `'Actual'` +- Allowed: + ```Bicep + [ + 'Actual' + 'Forecasted' + ] + ``` + ## Outputs | Output | Type | Description | diff --git a/avm/res/consumption/budget/main.bicep b/avm/res/consumption/budget/main.bicep index caa88053ae..4123efcb95 100644 --- a/avm/res/consumption/budget/main.bicep +++ b/avm/res/consumption/budget/main.bicep @@ -39,7 +39,7 @@ param endDate string = '' 'GreaterThan' 'GreaterThanOrEqualTo' ]) -@description('Required. The comparison operator. The operator can be either `EqualTo`, `GreaterThan`, or `GreaterThanOrEqualTo`.') +@description('Optional. The comparison operator. The operator can be either `EqualTo`, `GreaterThan`, or `GreaterThanOrEqualTo`.') param operator string = 'GreaterThan' @maxLength(5) @@ -65,7 +65,7 @@ param actionGroups array? 'Actual' 'Forecasted' ]) -@description('Required. The type of threshold to use for the budget. The threshold type can be either `Actual` or `Forecasted`.') +@description('Optional. The type of threshold to use for the budget. The threshold type can be either `Actual` or `Forecasted`.') param thresholdType string = 'Actual' @description('Optional. The filter to use for restricting which resources are considered within the budget.') diff --git a/avm/res/consumption/budget/main.json b/avm/res/consumption/budget/main.json index b68ced8a2d..3a0eed79e9 100644 --- a/avm/res/consumption/budget/main.json +++ b/avm/res/consumption/budget/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9899827298268482806" + "version": "0.30.23.60470", + "templateHash": "14721330685806821575" }, "name": "Consumption Budgets", "description": "This module deploys a Consumption Budget for Subscriptions.", @@ -74,7 +74,7 @@ "GreaterThanOrEqualTo" ], "metadata": { - "description": "Required. The comparison operator. The operator can be either `EqualTo`, `GreaterThan`, or `GreaterThanOrEqualTo`." + "description": "Optional. The comparison operator. The operator can be either `EqualTo`, `GreaterThan`, or `GreaterThanOrEqualTo`." } }, "thresholds": { @@ -120,7 +120,7 @@ "Forecasted" ], "metadata": { - "description": "Required. The type of threshold to use for the budget. The threshold type can be either `Actual` or `Forecasted`." + "description": "Optional. The type of threshold to use for the budget. The threshold type can be either `Actual` or `Forecasted`." } }, "filter": { diff --git a/avm/res/container-registry/registry/README.md b/avm/res/container-registry/registry/README.md index 4be75ae21b..4c2f170db8 100644 --- a/avm/res/container-registry/registry/README.md +++ b/avm/res/container-registry/registry/README.md @@ -1580,15 +1580,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1597,6 +1595,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/container-registry/registry/main.bicep b/avm/res/container-registry/registry/main.bicep index e164a1be14..9319bf65da 100644 --- a/avm/res/container-registry/registry/main.bicep +++ b/avm/res/container-registry/registry/main.bicep @@ -620,7 +620,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/container-registry/registry/main.json b/avm/res/container-registry/registry/main.json index a54cb59fe1..5e42d035ac 100644 --- a/avm/res/container-registry/registry/main.json +++ b/avm/res/container-registry/registry/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "14769734612544320664" + "version": "0.30.23.60470", + "templateHash": "2277340268999354626" }, "name": "Azure Container Registries (ACR)", "description": "This module deploys an Azure Container Registry (ACR).", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -1028,8 +1028,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "17045733538280748766" + "version": "0.30.23.60470", + "templateHash": "17963190751439748514" }, "name": "Container Registries scopeMaps", "description": "This module deploys an Azure Container Registry (ACR) scopeMap.", @@ -1155,8 +1155,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "11507205381257602922" + "version": "0.30.23.60470", + "templateHash": "4997004041066797666" }, "name": "Azure Container Registry (ACR) Replications", "description": "This module deploys an Azure Container Registry (ACR) Replication.", @@ -1303,8 +1303,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "13281764602355848660" + "version": "0.30.23.60470", + "templateHash": "7759513970094711275" }, "name": "Container Registries Credential Sets", "description": "This module deploys an ACR Credential Set.", @@ -1478,8 +1478,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "17205938486061573561" + "version": "0.30.23.60470", + "templateHash": "1396902957012921251" }, "name": "Container Registries Cache", "description": "Cache for Azure Container Registry (Preview) feature allows users to cache container images in a private container registry. Cache for ACR, is a preview feature available in Basic, Standard, and Premium service tiers ([ref](https://learn.microsoft.com/en-us/azure/container-registry/tutorial-registry-cache)).", @@ -1610,8 +1610,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "3542060088842117365" + "version": "0.30.23.60470", + "templateHash": "10216591470402784498" }, "name": "Azure Container Registry (ACR) Webhooks", "description": "This module deploys an Azure Container Registry (ACR) Webhook.", diff --git a/avm/res/container-service/managed-cluster/README.md b/avm/res/container-service/managed-cluster/README.md index 27d80860c1..8ff9e062da 100644 --- a/avm/res/container-service/managed-cluster/README.md +++ b/avm/res/container-service/managed-cluster/README.md @@ -35,9 +35,10 @@ The following section provides usage examples for the module, which were used to - [Using only defaults and use AKS Automatic mode](#example-1-using-only-defaults-and-use-aks-automatic-mode) - [Using Azure CNI Network Plugin.](#example-2-using-azure-cni-network-plugin) - [Using only defaults](#example-3-using-only-defaults) -- [Using Kubenet Network Plugin.](#example-4-using-kubenet-network-plugin) -- [Using Private Cluster.](#example-5-using-private-cluster) -- [WAF-aligned](#example-6-waf-aligned) +- [Using Istio Service Mesh add-on](#example-4-using-istio-service-mesh-add-on) +- [Using Kubenet Network Plugin.](#example-5-using-kubenet-network-plugin) +- [Using Private Cluster.](#example-6-using-private-cluster) +- [WAF-aligned](#example-7-waf-aligned) ### Example 1: _Using only defaults and use AKS Automatic mode_ @@ -59,10 +60,16 @@ module managedCluster 'br/public:avm/res/container-service/managed-cluster:' maintenanceConfigurations: [ { @@ -87,6 +94,17 @@ module managedCluster 'br/public:avm/res/container-service/managed-cluster:" }, @@ -147,6 +183,31 @@ module managedCluster 'br/public:avm/res/container-service/managed-cluster: @@ -1126,7 +1204,162 @@ param managedIdentities = {

    -### Example 4: _Using Kubenet Network Plugin._ +### Example 4: _Using Istio Service Mesh add-on_ + +This instance deploys the module with Istio Service Mesh add-on and plug a Certificate Authority from Key Vault. + + +

    + +via Bicep module + +```bicep +module managedCluster 'br/public:avm/res/container-service/managed-cluster:' = { + name: 'managedClusterDeployment' + params: { + // Required parameters + name: 'csist001' + primaryAgentPoolProfiles: [ + { + count: 3 + mode: 'System' + name: 'systempool' + vmSize: 'Standard_DS2_v2' + } + ] + // Non-required parameters + enableKeyvaultSecretsProvider: true + enableSecretRotation: true + istioServiceMeshCertificateAuthority: { + certChainObjectName: '' + certObjectName: '' + keyObjectName: '' + keyVaultResourceId: '' + rootCertObjectName: '' + } + istioServiceMeshEnabled: true + istioServiceMeshInternalIngressGatewayEnabled: true + istioServiceMeshRevisions: [ + 'asm-1-22' + ] + location: '' + managedIdentities: { + systemAssigned: true + } + } +} +``` + +
    +

    + +

    + +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "csist001" + }, + "primaryAgentPoolProfiles": { + "value": [ + { + "count": 3, + "mode": "System", + "name": "systempool", + "vmSize": "Standard_DS2_v2" + } + ] + }, + // Non-required parameters + "enableKeyvaultSecretsProvider": { + "value": true + }, + "enableSecretRotation": { + "value": true + }, + "istioServiceMeshCertificateAuthority": { + "value": { + "certChainObjectName": "", + "certObjectName": "", + "keyObjectName": "", + "keyVaultResourceId": "", + "rootCertObjectName": "" + } + }, + "istioServiceMeshEnabled": { + "value": true + }, + "istioServiceMeshInternalIngressGatewayEnabled": { + "value": true + }, + "istioServiceMeshRevisions": { + "value": [ + "asm-1-22" + ] + }, + "location": { + "value": "" + }, + "managedIdentities": { + "value": { + "systemAssigned": true + } + } + } +} +``` + +
    +

    + +

    + +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/container-service/managed-cluster:' + +// Required parameters +param name = 'csist001' +param primaryAgentPoolProfiles = [ + { + count: 3 + mode: 'System' + name: 'systempool' + vmSize: 'Standard_DS2_v2' + } +] +// Non-required parameters +param enableKeyvaultSecretsProvider = true +param enableSecretRotation = true +param istioServiceMeshCertificateAuthority = { + certChainObjectName: '' + certObjectName: '' + keyObjectName: '' + keyVaultResourceId: '' + rootCertObjectName: '' +} +param istioServiceMeshEnabled = true +param istioServiceMeshInternalIngressGatewayEnabled = true +param istioServiceMeshRevisions = [ + 'asm-1-22' +] +param location = '' +param managedIdentities = { + systemAssigned: true +} +``` + +
    +

    + +### Example 5: _Using Kubenet Network Plugin._ This instance deploys the module with Kubenet network plugin . @@ -1525,7 +1758,7 @@ param tags = {

    -### Example 5: _Using Private Cluster._ +### Example 6: _Using Private Cluster._ This instance deploys the module with a private cluster instance. @@ -1835,7 +2068,7 @@ param skuTier = 'Standard'

    -### Example 6: _WAF-aligned_ +### Example 7: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Well-Architected Framework. @@ -2475,6 +2708,11 @@ param tags = { | [`identityProfile`](#parameter-identityprofile) | object | Identities associated with the cluster. | | [`imageCleanerIntervalHours`](#parameter-imagecleanerintervalhours) | int | The interval in hours Image Cleaner will run. The maximum value is three months. | | [`ingressApplicationGatewayEnabled`](#parameter-ingressapplicationgatewayenabled) | bool | Specifies whether the ingressApplicationGateway (AGIC) add-on is enabled or not. | +| [`istioServiceMeshCertificateAuthority`](#parameter-istioservicemeshcertificateauthority) | object | The Istio Certificate Authority definition. | +| [`istioServiceMeshEnabled`](#parameter-istioservicemeshenabled) | bool | Specifies whether the Istio ServiceMesh add-on is enabled or not. | +| [`istioServiceMeshExternalIngressGatewayEnabled`](#parameter-istioservicemeshexternalingressgatewayenabled) | bool | Specifies whether the External Istio Ingress Gateway is enabled or not. | +| [`istioServiceMeshInternalIngressGatewayEnabled`](#parameter-istioservicemeshinternalingressgatewayenabled) | bool | Specifies whether the Internal Istio Ingress Gateway is enabled or not. | +| [`istioServiceMeshRevisions`](#parameter-istioservicemeshrevisions) | array | The list of revisions of the Istio control plane. When an upgrade is not in progress, this holds one value. When canary upgrade is in progress, this can only hold two consecutive values. | | [`kedaAddon`](#parameter-kedaaddon) | bool | Enables Kubernetes Event-driven Autoscaling (KEDA). | | [`kubeDashboardEnabled`](#parameter-kubedashboardenabled) | bool | Specifies whether the kubeDashboard add-on is enabled or not. | | [`kubernetesVersion`](#parameter-kubernetesversion) | string | Version of Kubernetes specified when creating the managed cluster. | @@ -2491,7 +2729,9 @@ param tags = { | [`networkPlugin`](#parameter-networkplugin) | string | Specifies the network plugin used for building Kubernetes network. | | [`networkPluginMode`](#parameter-networkpluginmode) | string | Network plugin mode used for building the Kubernetes network. Not compatible with kubenet network plugin. | | [`networkPolicy`](#parameter-networkpolicy) | string | Specifies the network policy used for building Kubernetes network. - calico or azure. | +| [`nodeProvisioningProfile`](#parameter-nodeprovisioningprofile) | object | Node provisioning settings that apply to the whole cluster. | | [`nodeResourceGroup`](#parameter-noderesourcegroup) | string | Name of the resource group containing agent pool nodes. | +| [`nodeResourceGroupProfile`](#parameter-noderesourcegroupprofile) | object | The node resource group configuration profile. | | [`omsAgentEnabled`](#parameter-omsagentenabled) | bool | Specifies whether the OMS agent is enabled. | | [`openServiceMeshEnabled`](#parameter-openservicemeshenabled) | bool | Specifies whether the openServiceMesh add-on is enabled or not. | | [`outboundType`](#parameter-outboundtype) | string | Specifies outbound (egress) routing method. | @@ -2504,6 +2744,7 @@ param tags = { | [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | Allow or deny public network access for AKS. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | | [`serviceCidr`](#parameter-servicecidr) | string | A CIDR notation IP range from which to assign service cluster IPs. It must not overlap with any Subnet IP ranges. | +| [`skuName`](#parameter-skuname) | string | Name of a managed cluster SKU. | | [`skuTier`](#parameter-skutier) | string | Tier of a managed cluster SKU. | | [`sshPublicKey`](#parameter-sshpublickey) | string | Specifies the SSH RSA public key string for the Linux nodes. | | [`supportPlan`](#parameter-supportplan) | string | The support plan for the Managed Cluster. | @@ -3973,13 +4214,6 @@ Settings and configurations for the flux extension. - Required: No - Type: object -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`name`](#parameter-fluxextensionname) | string | The name of the extension. | -| [`releaseTrain`](#parameter-fluxextensionreleasetrain) | string | The release train of the extension. | - **Optional parameters** | Parameter | Type | Description | @@ -3987,24 +4221,12 @@ Settings and configurations for the flux extension. | [`configurationProtectedSettings`](#parameter-fluxextensionconfigurationprotectedsettings) | object | The configuration protected settings of the extension. | | [`configurations`](#parameter-fluxextensionconfigurations) | array | The flux configurations of the extension. | | [`configurationSettings`](#parameter-fluxextensionconfigurationsettings) | object | The configuration settings of the extension. | +| [`name`](#parameter-fluxextensionname) | string | The name of the extension. | | [`releaseNamespace`](#parameter-fluxextensionreleasenamespace) | string | Namespace where the extension Release must be placed. | +| [`releaseTrain`](#parameter-fluxextensionreleasetrain) | string | The release train of the extension. | | [`targetNamespace`](#parameter-fluxextensiontargetnamespace) | string | Namespace where the extension will be created for an Namespace scoped extension. | | [`version`](#parameter-fluxextensionversion) | string | The version of the extension. | -### Parameter: `fluxExtension.name` - -The name of the extension. - -- Required: No -- Type: string - -### Parameter: `fluxExtension.releaseTrain` - -The release train of the extension. - -- Required: No -- Type: string - ### Parameter: `fluxExtension.configurationProtectedSettings` The configuration protected settings of the extension. @@ -4039,6 +4261,13 @@ The configuration settings of the extension. - Required: No - Type: object +### Parameter: `fluxExtension.name` + +The name of the extension. + +- Required: No +- Type: string + ### Parameter: `fluxExtension.releaseNamespace` Namespace where the extension Release must be placed. @@ -4046,6 +4275,13 @@ Namespace where the extension Release must be placed. - Required: No - Type: string +### Parameter: `fluxExtension.releaseTrain` + +The release train of the extension. + +- Required: No +- Type: string + ### Parameter: `fluxExtension.targetNamespace` Namespace where the extension will be created for an Namespace scoped extension. @@ -4098,6 +4334,89 @@ Specifies whether the ingressApplicationGateway (AGIC) add-on is enabled or not. - Type: bool - Default: `False` +### Parameter: `istioServiceMeshCertificateAuthority` + +The Istio Certificate Authority definition. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`certChainObjectName`](#parameter-istioservicemeshcertificateauthoritycertchainobjectname) | string | The Certificate chain object name in Azure Key Vault. | +| [`certObjectName`](#parameter-istioservicemeshcertificateauthoritycertobjectname) | string | The Intermediate certificate object name in Azure Key Vault. | +| [`keyObjectName`](#parameter-istioservicemeshcertificateauthoritykeyobjectname) | string | The Intermediate certificate private key object name in Azure Key Vault. | +| [`keyVaultResourceId`](#parameter-istioservicemeshcertificateauthoritykeyvaultresourceid) | string | The resource ID of a key vault to reference a Certificate Authority from. | +| [`rootCertObjectName`](#parameter-istioservicemeshcertificateauthorityrootcertobjectname) | string | Root certificate object name in Azure Key Vault. | + +### Parameter: `istioServiceMeshCertificateAuthority.certChainObjectName` + +The Certificate chain object name in Azure Key Vault. + +- Required: Yes +- Type: string + +### Parameter: `istioServiceMeshCertificateAuthority.certObjectName` + +The Intermediate certificate object name in Azure Key Vault. + +- Required: Yes +- Type: string + +### Parameter: `istioServiceMeshCertificateAuthority.keyObjectName` + +The Intermediate certificate private key object name in Azure Key Vault. + +- Required: Yes +- Type: string + +### Parameter: `istioServiceMeshCertificateAuthority.keyVaultResourceId` + +The resource ID of a key vault to reference a Certificate Authority from. + +- Required: Yes +- Type: string + +### Parameter: `istioServiceMeshCertificateAuthority.rootCertObjectName` + +Root certificate object name in Azure Key Vault. + +- Required: Yes +- Type: string + +### Parameter: `istioServiceMeshEnabled` + +Specifies whether the Istio ServiceMesh add-on is enabled or not. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `istioServiceMeshExternalIngressGatewayEnabled` + +Specifies whether the External Istio Ingress Gateway is enabled or not. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `istioServiceMeshInternalIngressGatewayEnabled` + +Specifies whether the Internal Istio Ingress Gateway is enabled or not. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `istioServiceMeshRevisions` + +The list of revisions of the Istio control plane. When an upgrade is not in progress, this holds one value. When canary upgrade is in progress, this can only hold two consecutive values. + +- Required: No +- Type: array + ### Parameter: `kedaAddon` Enables Kubernetes Event-driven Autoscaling (KEDA). @@ -4326,9 +4645,17 @@ Specifies the network policy used for building Kubernetes network. - calico or a [ 'azure' 'calico' + 'cilium' ] ``` +### Parameter: `nodeProvisioningProfile` + +Node provisioning settings that apply to the whole cluster. + +- Required: No +- Type: object + ### Parameter: `nodeResourceGroup` Name of the resource group containing agent pool nodes. @@ -4337,6 +4664,13 @@ Name of the resource group containing agent pool nodes. - Type: string - Default: `[format('{0}_aks_{1}_nodes', resourceGroup().name, parameters('name'))]` +### Parameter: `nodeResourceGroupProfile` + +The node resource group configuration profile. + +- Required: No +- Type: object + ### Parameter: `omsAgentEnabled` Specifies whether the OMS agent is enabled. @@ -4554,6 +4888,21 @@ A CIDR notation IP range from which to assign service cluster IPs. It must not o - Required: No - Type: string +### Parameter: `skuName` + +Name of a managed cluster SKU. + +- Required: No +- Type: string +- Default: `'Base'` +- Allowed: + ```Bicep + [ + 'Automatic' + 'Base' + ] + ``` + ### Parameter: `skuTier` Tier of a managed cluster SKU. diff --git a/avm/res/container-service/managed-cluster/agent-pool/main.json b/avm/res/container-service/managed-cluster/agent-pool/main.json index 65a21588ad..11965a3fab 100644 --- a/avm/res/container-service/managed-cluster/agent-pool/main.json +++ b/avm/res/container-service/managed-cluster/agent-pool/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13856766172443517827" + "version": "0.31.34.60546", + "templateHash": "13504241837980660061" }, "name": "Azure Kubernetes Service (AKS) Managed Cluster Agent Pools", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster Agent Pool.", @@ -355,10 +355,7 @@ "vmSize": "[parameters('vmSize')]", "vnetSubnetID": "[parameters('vnetSubnetResourceId')]", "workloadRuntime": "[parameters('workloadRuntime')]" - }, - "dependsOn": [ - "managedCluster" - ] + } } }, "outputs": { diff --git a/avm/res/container-service/managed-cluster/main.bicep b/avm/res/container-service/managed-cluster/main.bicep index 88a8d6a89b..3aecff5f78 100644 --- a/avm/res/container-service/managed-cluster/main.bicep +++ b/avm/res/container-service/managed-cluster/main.bicep @@ -38,6 +38,7 @@ param networkPluginMode string? @allowed([ 'azure' 'calico' + 'cilium' ]) param networkPolicy string? @@ -76,6 +77,13 @@ param backendPoolType string = 'NodeIPConfiguration' ]) param outboundType string = 'loadBalancer' +@description('Optional. Name of a managed cluster SKU.') +@allowed([ + 'Base' + 'Automatic' +]) +param skuName string = 'Base' + @description('Optional. Tier of a managed cluster SKU.') @allowed([ 'Free' @@ -124,9 +132,15 @@ param aadProfileEnableAzureRBAC bool = enableRBAC @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 = true +@description('Optional. Node provisioning settings that apply to the whole cluster.') +param nodeProvisioningProfile object? + @description('Optional. Name of the resource group containing agent pool nodes.') param nodeResourceGroup string = '${resourceGroup().name}_aks_${name}_nodes' +@description('Optional. The node resource group configuration profile.') +param nodeResourceGroupProfile object? + @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 string[]? @@ -392,6 +406,21 @@ param metricLabelsAllowlist string = '' @description('Optional. A comma-separated list of Kubernetes cluster metrics annotations.') param metricAnnotationsAllowList string = '' +@description('Optional. Specifies whether the Istio ServiceMesh add-on is enabled or not.') +param istioServiceMeshEnabled bool = false + +@description('Optional. The list of revisions of the Istio control plane. When an upgrade is not in progress, this holds one value. When canary upgrade is in progress, this can only hold two consecutive values.') +param istioServiceMeshRevisions array? + +@description('Optional. Specifies whether the Internal Istio Ingress Gateway is enabled or not.') +param istioServiceMeshInternalIngressGatewayEnabled bool = false + +@description('Optional. Specifies whether the External Istio Ingress Gateway is enabled or not.') +param istioServiceMeshExternalIngressGatewayEnabled bool = false + +@description('Optional. The Istio Certificate Authority definition.') +param istioServiceMeshCertificateAuthority istioServiceMeshCertificateAuthorityType + // =========== // // Variables // // =========== // @@ -537,7 +566,7 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2024-03-02-p tags: tags identity: identity sku: { - name: 'Base' + name: skuName tier: skuTier } properties: { @@ -678,6 +707,8 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2024-03-02-p enableRBAC: enableRBAC disableLocalAccounts: disableLocalAccounts nodeResourceGroup: nodeResourceGroup + nodeResourceGroupProfile: nodeResourceGroupProfile + nodeProvisioningProfile: nodeProvisioningProfile enablePodSecurityPolicy: enablePodSecurityPolicy workloadAutoScalerProfile: { keda: { @@ -690,8 +721,8 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2024-03-02-p networkProfile: { networkDataplane: networkDataplane networkPlugin: networkPlugin - networkPluginMode: networkPluginMode - networkPolicy: networkPolicy + networkPluginMode: networkDataplane == 'cilium' ? 'overlay' : networkPluginMode + networkPolicy: networkDataplane == 'cilium' ? 'cilium' : networkPolicy podCidr: podCidr serviceCidr: serviceCidr dnsServiceIP: dnsServiceIP @@ -811,6 +842,37 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2024-03-02-p } } supportPlan: supportPlan + serviceMeshProfile: istioServiceMeshEnabled + ? { + istio: { + revisions: !empty(istioServiceMeshRevisions) ? istioServiceMeshRevisions : null + components: { + ingressGateways: [ + { + enabled: istioServiceMeshInternalIngressGatewayEnabled + mode: 'Internal' + } + { + enabled: istioServiceMeshExternalIngressGatewayEnabled + mode: 'External' + } + ] + } + certificateAuthority: !empty(istioServiceMeshCertificateAuthority) + ? { + plugin: { + certChainObjectName: istioServiceMeshCertificateAuthority.?certChainObjectName + certObjectName: istioServiceMeshCertificateAuthority.?certObjectName + keyObjectName: istioServiceMeshCertificateAuthority.?keyObjectName + keyVaultId: istioServiceMeshCertificateAuthority.?keyVaultResourceId + rootCertObjectName: istioServiceMeshCertificateAuthority.?rootCertObjectName + } + } + : null + } + mode: 'Istio' + } + : null } } @@ -879,7 +941,7 @@ module managedCluster_extension 'br/public:avm/res/kubernetes-configuration/exte extensionType: 'microsoft.flux' fluxConfigurations: fluxExtension.?configurations location: location - name: 'flux' + name: fluxExtension.?name ?? 'flux' releaseNamespace: fluxExtension.?releaseNamespace ?? 'flux-system' releaseTrain: fluxExtension.?releaseTrain ?? 'Stable' version: fluxExtension.?version @@ -1229,7 +1291,7 @@ type fluxConfigurationProtectedSettingsType = { @export() type extensionType = { - @description('Required. The name of the extension.') + @description('Optional. The name of the extension.') name: string? @description('Optional. Namespace where the extension Release must be placed.') @@ -1238,7 +1300,7 @@ type extensionType = { @description('Optional. Namespace where the extension will be created for an Namespace scoped extension.') targetNamespace: string? - @description('Required. The release train of the extension.') + @description('Optional. The release train of the extension.') releaseTrain: string? @description('Optional. The configuration protected settings of the extension.') @@ -1276,4 +1338,21 @@ type maintenanceConfigurationType = { @description('Required. Maintenance window for the maintenance configuration.') maintenanceWindow: object -} +}? + +type istioServiceMeshCertificateAuthorityType = { + @description('Required. The resource ID of a key vault to reference a Certificate Authority from.') + keyVaultResourceId: string + + @description('Required. The Certificate chain object name in Azure Key Vault.') + certChainObjectName: string + + @description('Required. The Intermediate certificate object name in Azure Key Vault.') + certObjectName: string + + @description('Required. The Intermediate certificate private key object name in Azure Key Vault.') + keyObjectName: string + + @description('Required. Root certificate object name in Azure Key Vault.') + rootCertObjectName: string +}? diff --git a/avm/res/container-service/managed-cluster/main.json b/avm/res/container-service/managed-cluster/main.json index c0c9f95d89..3f20739576 100644 --- a/avm/res/container-service/managed-cluster/main.json +++ b/avm/res/container-service/managed-cluster/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14675004991337717729" + "version": "0.31.34.60546", + "templateHash": "178765084464759811" }, "name": "Azure Kubernetes Service (AKS) Managed Clusters", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster.", @@ -591,7 +591,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. The name of the extension." + "description": "Optional. The name of the extension." } }, "releaseNamespace": { @@ -612,7 +612,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. The release train of the extension." + "description": "Optional. The release train of the extension." } }, "configurationProtectedSettings": { @@ -705,9 +705,46 @@ } } }, + "nullable": true, "metadata": { "__bicep_export!": true } + }, + "istioServiceMeshCertificateAuthorityType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a Certificate Authority from." + } + }, + "certChainObjectName": { + "type": "string", + "metadata": { + "description": "Required. The Certificate chain object name in Azure Key Vault." + } + }, + "certObjectName": { + "type": "string", + "metadata": { + "description": "Required. The Intermediate certificate object name in Azure Key Vault." + } + }, + "keyObjectName": { + "type": "string", + "metadata": { + "description": "Required. The Intermediate certificate private key object name in Azure Key Vault." + } + }, + "rootCertObjectName": { + "type": "string", + "metadata": { + "description": "Required. Root certificate object name in Azure Key Vault." + } + } + }, + "nullable": true } }, "parameters": { @@ -775,7 +812,8 @@ "nullable": true, "allowedValues": [ "azure", - "calico" + "calico", + "cilium" ], "metadata": { "description": "Optional. Specifies the network policy used for building Kubernetes network. - calico or azure." @@ -844,6 +882,17 @@ "description": "Optional. Specifies outbound (egress) routing method." } }, + "skuName": { + "type": "string", + "defaultValue": "Base", + "allowedValues": [ + "Base", + "Automatic" + ], + "metadata": { + "description": "Optional. Name of a managed cluster SKU." + } + }, "skuTier": { "type": "string", "defaultValue": "Standard", @@ -950,6 +999,13 @@ "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." } }, + "nodeProvisioningProfile": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Node provisioning settings that apply to the whole cluster." + } + }, "nodeResourceGroup": { "type": "string", "defaultValue": "[format('{0}_aks_{1}_nodes', resourceGroup().name, parameters('name'))]", @@ -957,6 +1013,13 @@ "description": "Optional. Name of the resource group containing agent pool nodes." } }, + "nodeResourceGroupProfile": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The node resource group configuration profile." + } + }, "authorizedIPRanges": { "type": "array", "items": { @@ -1539,6 +1602,40 @@ "metadata": { "description": "Optional. A comma-separated list of Kubernetes cluster metrics annotations." } + }, + "istioServiceMeshEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether the Istio ServiceMesh add-on is enabled or not." + } + }, + "istioServiceMeshRevisions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of revisions of the Istio control plane. When an upgrade is not in progress, this holds one value. When canary upgrade is in progress, this can only hold two consecutive values." + } + }, + "istioServiceMeshInternalIngressGatewayEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether the Internal Istio Ingress Gateway is enabled or not." + } + }, + "istioServiceMeshExternalIngressGatewayEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether the External Istio Ingress Gateway is enabled or not." + } + }, + "istioServiceMeshCertificateAuthority": { + "$ref": "#/definitions/istioServiceMeshCertificateAuthorityType", + "metadata": { + "description": "Optional. The Istio Certificate Authority definition." + } } }, "variables": { @@ -1581,10 +1678,7 @@ "apiVersion": "2023-02-01", "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", - "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKey'), 'keyName'), 'dummyKey'))]", - "dependsOn": [ - "cMKKeyVault" - ] + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKey'), 'keyName'), 'dummyKey'))]" }, "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", @@ -1623,7 +1717,7 @@ "tags": "[parameters('tags')]", "identity": "[variables('identity')]", "sku": { - "name": "Base", + "name": "[parameters('skuName')]", "tier": "[parameters('skuTier')]" }, "properties": { @@ -1681,6 +1775,8 @@ "enableRBAC": "[parameters('enableRBAC')]", "disableLocalAccounts": "[parameters('disableLocalAccounts')]", "nodeResourceGroup": "[parameters('nodeResourceGroup')]", + "nodeResourceGroupProfile": "[parameters('nodeResourceGroupProfile')]", + "nodeProvisioningProfile": "[parameters('nodeProvisioningProfile')]", "enablePodSecurityPolicy": "[parameters('enablePodSecurityPolicy')]", "workloadAutoScalerProfile": { "keda": { @@ -1693,8 +1789,8 @@ "networkProfile": { "networkDataplane": "[parameters('networkDataplane')]", "networkPlugin": "[parameters('networkPlugin')]", - "networkPluginMode": "[parameters('networkPluginMode')]", - "networkPolicy": "[parameters('networkPolicy')]", + "networkPluginMode": "[if(equals(parameters('networkDataplane'), 'cilium'), 'overlay', parameters('networkPluginMode'))]", + "networkPolicy": "[if(equals(parameters('networkDataplane'), 'cilium'), 'cilium', parameters('networkPolicy'))]", "podCidr": "[parameters('podCidr')]", "serviceCidr": "[parameters('serviceCidr')]", "dnsServiceIP": "[parameters('dnsServiceIP')]", @@ -1775,7 +1871,8 @@ "enabled": "[parameters('enableStorageProfileSnapshotController')]" } }, - "supportPlan": "[parameters('supportPlan')]" + "supportPlan": "[parameters('supportPlan')]", + "serviceMeshProfile": "[if(parameters('istioServiceMeshEnabled'), createObject('istio', createObject('revisions', if(not(empty(parameters('istioServiceMeshRevisions'))), parameters('istioServiceMeshRevisions'), null()), 'components', createObject('ingressGateways', createArray(createObject('enabled', parameters('istioServiceMeshInternalIngressGatewayEnabled'), 'mode', 'Internal'), createObject('enabled', parameters('istioServiceMeshExternalIngressGatewayEnabled'), 'mode', 'External'))), 'certificateAuthority', if(not(empty(parameters('istioServiceMeshCertificateAuthority'))), createObject('plugin', createObject('certChainObjectName', tryGet(parameters('istioServiceMeshCertificateAuthority'), 'certChainObjectName'), 'certObjectName', tryGet(parameters('istioServiceMeshCertificateAuthority'), 'certObjectName'), 'keyObjectName', tryGet(parameters('istioServiceMeshCertificateAuthority'), 'keyObjectName'), 'keyVaultId', tryGet(parameters('istioServiceMeshCertificateAuthority'), 'keyVaultResourceId'), 'rootCertObjectName', tryGet(parameters('istioServiceMeshCertificateAuthority'), 'rootCertObjectName'))), null())), 'mode', 'Istio'), null())]" } }, "managedCluster_lock": { @@ -1908,8 +2005,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2505380725266419010" + "version": "0.31.34.60546", + "templateHash": "3191846535289543816" }, "name": "Azure Kubernetes Service (AKS) Managed Cluster Maintenance Configurations", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster Maintenance Configurations.", @@ -2105,8 +2202,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13856766172443517827" + "version": "0.31.34.60546", + "templateHash": "13504241837980660061" }, "name": "Azure Kubernetes Service (AKS) Managed Cluster Agent Pools", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster Agent Pool.", @@ -2455,10 +2552,7 @@ "vmSize": "[parameters('vmSize')]", "vnetSubnetID": "[parameters('vnetSubnetResourceId')]", "workloadRuntime": "[parameters('workloadRuntime')]" - }, - "dependsOn": [ - "managedCluster" - ] + } } }, "outputs": { @@ -2523,7 +2617,7 @@ "value": "[parameters('location')]" }, "name": { - "value": "flux" + "value": "[coalesce(tryGet(parameters('fluxExtension'), 'name'), 'flux')]" }, "releaseNamespace": { "value": "[coalesce(tryGet(parameters('fluxExtension'), 'releaseNamespace'), 'flux-system')]" diff --git a/avm/res/container-service/managed-cluster/maintenance-configurations/main.json b/avm/res/container-service/managed-cluster/maintenance-configurations/main.json index 22e9300b85..64b5e4c229 100644 --- a/avm/res/container-service/managed-cluster/maintenance-configurations/main.json +++ b/avm/res/container-service/managed-cluster/maintenance-configurations/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "2505380725266419010" + "version": "0.31.34.60546", + "templateHash": "3191846535289543816" }, "name": "Azure Kubernetes Service (AKS) Managed Cluster Maintenance Configurations", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster Maintenance Configurations.", diff --git a/avm/res/container-service/managed-cluster/tests/e2e/automatic/main.test.bicep b/avm/res/container-service/managed-cluster/tests/e2e/automatic/main.test.bicep index 7852289f4c..1e45f1c1bf 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/automatic/main.test.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/automatic/main.test.bicep @@ -39,6 +39,12 @@ module testDeployment '../../../main.bicep' = [ params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation + autoNodeOsUpgradeProfileUpgradeChannel: 'NodeImage' + disableLocalAccounts: true + enableKeyvaultSecretsProvider: true + enableSecretRotation: true + kedaAddon: true + kubernetesVersion: '1.28' maintenanceConfigurations: [ { name: 'aksManagedAutoUpgradeSchedule' @@ -62,14 +68,25 @@ module testDeployment '../../../main.bicep' = [ managedIdentities: { systemAssigned: true } + nodeProvisioningProfile: { + mode: 'Auto' + } + nodeResourceGroupProfile: { + restrictionLevel: 'ReadOnly' + } + outboundType: 'managedNATGateway' primaryAgentPoolProfiles: [ { name: 'systempool' count: 3 - vmSize: 'Standard_DS2_v2' + vmSize: 'Standard_DS4_v2' mode: 'System' } ] + publicNetworkAccess: 'Enabled' + skuName: 'Automatic' + vpaAddon: true + webApplicationRoutingEnabled: true } } ] diff --git a/avm/res/container-service/managed-cluster/tests/e2e/istio/dependencies.bicep b/avm/res/container-service/managed-cluster/tests/e2e/istio/dependencies.bicep new file mode 100644 index 0000000000..ff0496b6e1 --- /dev/null +++ b/avm/res/container-service/managed-cluster/tests/e2e/istio/dependencies.bicep @@ -0,0 +1,96 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the organization to which the Root Certificate is issued. It helps identify the legal entity that owns the root certificate') +param rootOrganization string + +@description('Required. The name of the organization to which the Certificate Authority is issued. It helps identify the legal entity that owns the certificate authority') +param caOrganization string + +@description('Required. The subject distinguished name is the name of the user of the certificate authority. The distinguished name for the certificate is a textual representation of the subject or issuer of the certificate') +param caSubjectName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Deployment Script to create for the Certificate generation.') +param cacertDeploymentScriptName string + +@description('Optional. Do not provide a value. Used to force the deployment script to rerun on every redeployment.') +param utcValue string = utcNow() + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: null + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${managedIdentity.name}-KeyVault-Admin-RoleAssignment') + scope: keyVault + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '00482a5a-887f-4fb3-b363-3b7fe8e74483' + ) // Key Vault Administrator + principalType: 'ServicePrincipal' + } +} + +resource cacertDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: cacertDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '11.0' + retentionInterval: 'P1D' + forceUpdateTag: utcValue + arguments: ' -KeyVaultName "${keyVault.name}" -RootOrganization "${rootOrganization}" -CAOrganization "${caOrganization}" -CertSubjectName "${caSubjectName}"' + scriptContent: loadTextContent('scripts/Set-CertificateAuthorityInKeyVault.ps1') + } +} + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The name of the root certificate secret.') +output rootCertSecretName string = cacertDeploymentScript.properties.outputs.rootCertSecretName + +@description('The name of the certiticate authority key secret.') +output caKeySecretName string = cacertDeploymentScript.properties.outputs.caKeySecretName + +@description('The name of the certificate authority cert secret.') +output caCertSecretName string = cacertDeploymentScript.properties.outputs.caCertSecretName + +@description('The name of the certificate chain secret.') +output certChainSecretName string = cacertDeploymentScript.properties.outputs.certChainSecretName + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/container-service/managed-cluster/tests/e2e/istio/main.rbac.bicep b/avm/res/container-service/managed-cluster/tests/e2e/istio/main.rbac.bicep new file mode 100644 index 0000000000..56a1220b2f --- /dev/null +++ b/avm/res/container-service/managed-cluster/tests/e2e/istio/main.rbac.bicep @@ -0,0 +1,22 @@ +@description('The resource ID of the Key Vault.') +param keyVaultResourceId string + +@description('The principal ID of the managed identity.') +param principalId string + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { + name: last(split(keyVaultResourceId, '/')) +} + +resource secretPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: keyVault + name: guid('msi-${principalId}-KeyVault-Secret-User-RoleAssignment') + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4633458b-17de-408a-b874-0445c86b69e6' + ) // Key Vault Secrets User + principalType: 'ServicePrincipal' + } +} diff --git a/avm/res/container-service/managed-cluster/tests/e2e/istio/main.test.bicep b/avm/res/container-service/managed-cluster/tests/e2e/istio/main.test.bicep new file mode 100644 index 0000000000..9753edb426 --- /dev/null +++ b/avm/res/container-service/managed-cluster/tests/e2e/istio/main.test.bicep @@ -0,0 +1,91 @@ +targetScope = 'subscription' + +metadata name = 'Using Istio Service Mesh add-on' +metadata description = 'This instance deploys the module with Istio Service Mesh add-on and plug a Certificate Authority from Key Vault.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-containerservice.managedclusters-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'csist' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + rootOrganization: 'Istio' + caOrganization: 'Istio' + caSubjectName: 'istiod.aks-istio.system.svc' + cacertDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + managedIdentities: { + systemAssigned: true + } + primaryAgentPoolProfiles: [ + { + name: 'systempool' + count: 3 + vmSize: 'Standard_DS2_v2' + mode: 'System' + } + ] + istioServiceMeshEnabled: true + istioServiceMeshInternalIngressGatewayEnabled: true + istioServiceMeshRevisions: [ + 'asm-1-22' + ] + istioServiceMeshCertificateAuthority: { + certChainObjectName: nestedDependencies.outputs.certChainSecretName + certObjectName: nestedDependencies.outputs.caCertSecretName + keyObjectName: nestedDependencies.outputs.caKeySecretName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + rootCertObjectName: nestedDependencies.outputs.rootCertSecretName + } + enableKeyvaultSecretsProvider: true + enableSecretRotation: true + } + } +] + +module secretPermissions 'main.rbac.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-rbac' + params: { + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + principalId: testDeployment[0].outputs.keyvaultIdentityObjectId + } +} diff --git a/avm/res/container-service/managed-cluster/tests/e2e/istio/scripts/Set-CertificateAuthorityInKeyVault.ps1 b/avm/res/container-service/managed-cluster/tests/e2e/istio/scripts/Set-CertificateAuthorityInKeyVault.ps1 new file mode 100644 index 0000000000..d61d7c8933 --- /dev/null +++ b/avm/res/container-service/managed-cluster/tests/e2e/istio/scripts/Set-CertificateAuthorityInKeyVault.ps1 @@ -0,0 +1,168 @@ +<# +.SYNOPSIS +Generate a new Certificate Authority and store it as secret in the given Key Vault. + +.DESCRIPTION +Generate a new Certificate Authority and store it as secret in the given Key Vault. + +.PARAMETER KeyVaultName +Mandatory. The name of the Key Vault to add a new certificate to, or fetch the secret reference it from + +.PARAMETER RootOrganization +Mandatory. The name of the organization to which the Root Certificate is issued. It helps identify the legal entity that owns the root certificate + +.PARAMETER CAOrganization +Mandatory. The name of the organization to which the Certificate Authority is issued. It helps identify the legal entity that owns the certificate authority + +.PARAMETER CertSubjectName +Mandatory. The subject distinguished name is the name of the user of the certificate authority. The distinguished name for the certificate is a textual representation of the subject or issuer of the certificate + +.EXAMPLE +./Set-CertificateAuthorityInKeyVault.ps1 -KeyVaultName 'myVault' -RootOrganization 'Istio' -CAOrganization 'Istio' -CertSubjectName 'istiod.aks-istio-system.com' + +Generate a Certificate Authority and store it in the Key Vault 'myVault' with the provided organizations and subject name +#> +param( + [Parameter(Mandatory = $true)] + [string] $KeyVaultName, + + [Parameter(Mandatory = $true)] + [string] $RootOrganization, + + [Parameter(Mandatory = $true)] + [string] $CAOrganization, + + [Parameter(Mandatory = $true)] + [string] $CertSubjectName +) + +$rootKeyFile = 'root-key.pem' +$rootKeySize = 4096 + +Write-Verbose ('Generating root key [{0}]' -f $rootKeyFile) -Verbose + +openssl genrsa -out $rootKeyFile $rootKeySize + +$rootKeyContent = Get-Content -Path $rootKeyFile -Raw +$rootKeyContentSecureString = ConvertTo-SecureString -String $rootKeyContent -AsPlainText -Force +$rootKeySecretName = 'root-key' +Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name $rootKeySecretName -SecretValue $rootKeyContentSecureString + +$rootConfFile = 'root-ca.conf' +$rootCommonName = 'Root CA' +$rootConfContent = @" +[ req ] +encrypt_key = no +prompt = no +utf8 = yes +default_md = sha256 +default_bits = $($rootKeySize) +req_extensions = req_ext +x509_extensions = req_ext +distinguished_name = req_dn +[ req_ext ] +subjectKeyIdentifier = hash +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, keyCertSign +[ req_dn ] +O = $($RootOrganization) +CN = $($rootCommonName) +"@ + +Write-Verbose ('Generating openssl config file [{0}]' -f $rootConfFile) -Verbose + +$rootConfContent | Set-Content -Path $rootConfFile + +$rootCertCSRFile = 'root-cert.csr' + +Write-Verbose ('Generating certificate signing request [{0}]' -f $rootCertCSRFile) -Verbose + +openssl req -sha256 -new -key $rootKeyFile -config $rootConfFile -out $rootCertCSRFile + +$rootCertFile = 'root-cert.pem' +$rootCertDays = 3650 + +Write-Verbose ('Generating root cert [{0}]' -f $rootCertFile) -Verbose + +openssl x509 -req -sha256 -days $rootCertDays -signkey $rootKeyFile -extensions req_ext -extfile $rootConfFile -in $rootCertCSRFile -out $rootCertFile + +$rootCertContent = Get-Content -Path $rootCertFile -Raw +$rootCertContentSecureString = ConvertTo-SecureString -String $rootCertContent -AsPlainText -Force +$rootCertSecretName = 'root-cert' +Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name $rootCertSecretName -SecretValue $rootCertContentSecureString + +$caKeyFile = 'ca-key.pem' +$caKeySize = '4096' + +Write-Verbose ('Generating ca key [{0}]' -f $caKeyFile) -Verbose + +openssl genrsa -out $caKeyFile $caKeySize + +$caKeyContent = Get-Content -Path $caKeyFile -Raw +$caKeyContentSecureString = ConvertTo-SecureString -String $caKeyContent -AsPlainText -Force +$caKeySecretName = 'ca-key' +Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name $caKeySecretName -SecretValue $caKeyContentSecureString + +$caConfFile = 'ca.conf' +$caCommonName = 'Intermediate CA' +$caConfLocation = Split-Path -Leaf (Get-Location) +$caConfContent = @" +[ req ] +encrypt_key = no +prompt = no +utf8 = yes +default_md = sha256 +default_bits = $($caKeySize) +req_extensions = req_ext +x509_extensions = req_ext +distinguished_name = req_dn +[ req_ext ] +subjectKeyIdentifier = hash +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, keyCertSign +subjectAltName=@san +[ san ] +DNS.1 = $($CertSubjectName) +[ req_dn ] +O = $($CAOrganization) +CN = $($caCommonName) +L = $($caConfLocation) +"@ + +Write-Verbose ('Generating openssl config file [{0}]' -f $caConfFile) -Verbose + +$caConfContent | Set-Content -Path $caConfFile + +$caCertCSRFile = 'ca-cert.csr' + +Write-Verbose ('Generating certificate signing request [{0}]' -f $caCertCSRFile) -Verbose + +openssl req -sha256 -new -key $caKeyFile -config $caConfFile -out $caCertCSRFile + +$caCertFile = 'ca-cert.pem' +$caCertDays = 3650 + +Write-Verbose ('Generating ca cert [{0}]' -f $caCertFile) -Verbose + +openssl x509 -req -sha256 -days $caCertDays -CA $rootCertFile -CAkey $rootKeyFile -CAcreateserial -extensions req_ext -extfile $caConfFile -in $caCertCSRFile -out $caCertFile + +$caCertContent = Get-Content -Path $caCertFile -Raw +$caCertContentSecureString = ConvertTo-SecureString -String $caCertContent -AsPlainText -Force +$caCertSecretName = 'ca-cert' +Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name $caCertSecretName -SecretValue $caCertContentSecureString + +Write-Verbose 'Generating cert chain' -Verbose + +$certChainContent = $caCertContent + $rootCertContent +$certChainContentSecureString = ConvertTo-SecureString -String $certChainContent -AsPlainText -Force +$certChainSecretName = 'cert-chain' +Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name $certChainSecretName -SecretValue $certChainContentSecureString + +# Write into Deployment Script output stream +$DeploymentScriptOutputs = @{ + rootKeySecretName = $rootKeySecretName + rootCertSecretName = $rootCertSecretName + caKeySecretName = $caKeySecretName + caCertSecretName = $caCertSecretName + certChainSecretName = $certChainSecretName +} diff --git a/avm/res/container-service/managed-cluster/version.json b/avm/res/container-service/managed-cluster/version.json index 13669e6601..41fc8c654f 100644 --- a/avm/res/container-service/managed-cluster/version.json +++ b/avm/res/container-service/managed-cluster/version.json @@ -1,7 +1,7 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.5", "pathFilters": [ "./main.json" ] -} \ No newline at end of file +} diff --git a/avm/res/data-factory/factory/README.md b/avm/res/data-factory/factory/README.md index 6ac0a9c7ce..2db45286df 100644 --- a/avm/res/data-factory/factory/README.md +++ b/avm/res/data-factory/factory/README.md @@ -1401,15 +1401,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1418,6 +1416,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/data-factory/factory/main.bicep b/avm/res/data-factory/factory/main.bicep index 5bb934d5a0..a398a32aab 100644 --- a/avm/res/data-factory/factory/main.bicep +++ b/avm/res/data-factory/factory/main.bicep @@ -483,7 +483,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/data-factory/factory/main.json b/avm/res/data-factory/factory/main.json index 5e8ffea4e0..aef90082e0 100644 --- a/avm/res/data-factory/factory/main.json +++ b/avm/res/data-factory/factory/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "15687596888855868361" + "templateHash": "16698009861031821081" }, "name": "Data Factories", "description": "This module deploys a Data Factory.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { diff --git a/avm/res/databricks/workspace/README.md b/avm/res/databricks/workspace/README.md index 1514771878..e8c32dccc9 100644 --- a/avm/res/databricks/workspace/README.md +++ b/avm/res/databricks/workspace/README.md @@ -1520,15 +1520,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1537,6 +1535,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -2115,15 +2120,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-storageaccountprivateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-storageaccountprivateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `storageAccountPrivateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-storageaccountprivateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `storageAccountPrivateEndpoints.customDnsConfigs.ipAddresses` @@ -2132,6 +2135,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `storageAccountPrivateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `storageAccountPrivateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/databricks/workspace/main.bicep b/avm/res/databricks/workspace/main.bicep index 5f3d0e7cdc..7b0ae9c266 100644 --- a/avm/res/databricks/workspace/main.bicep +++ b/avm/res/databricks/workspace/main.bicep @@ -218,139 +218,132 @@ resource workspace 'Microsoft.Databricks/workspaces@2024-05-01' = { sku: { name: skuName } - // This union is required because the defaultStorageFirewall property is optional and cannot be null or '' - properties: union( - { - managedResourceGroupId: !empty(managedResourceGroupResourceId) - ? managedResourceGroupResourceId - : '${subscription().id}/resourceGroups/rg-${name}-managed' - parameters: union( - // Always added parameters - { - enableNoPublicIp: { - value: disablePublicIp - } - prepareEncryption: { - value: prepareEncryption - } - vnetAddressPrefix: { - value: vnetAddressPrefix - } - requireInfrastructureEncryption: { - value: requireInfrastructureEncryption - } - }, - // Parameters only added if not empty - !empty(customVirtualNetworkResourceId) - ? { - customVirtualNetworkId: { - value: customVirtualNetworkResourceId - } - } - : {}, - !empty(amlWorkspaceResourceId) - ? { - amlWorkspaceId: { - value: amlWorkspaceResourceId - } + properties: { + managedResourceGroupId: !empty(managedResourceGroupResourceId) + ? managedResourceGroupResourceId + : '${subscription().id}/resourceGroups/rg-${name}-managed' + parameters: { + enableNoPublicIp: { + value: disablePublicIp + } + prepareEncryption: { + value: prepareEncryption + } + vnetAddressPrefix: { + value: vnetAddressPrefix + } + requireInfrastructureEncryption: { + value: requireInfrastructureEncryption + } + ...(!empty(customVirtualNetworkResourceId) + ? { + customVirtualNetworkId: { + value: customVirtualNetworkResourceId } - : {}, - !empty(customPrivateSubnetName) - ? { - customPrivateSubnetName: { - value: customPrivateSubnetName - } + } + : {}) + ...(!empty(amlWorkspaceResourceId) + ? { + amlWorkspaceId: { + value: amlWorkspaceResourceId } - : {}, - !empty(customPublicSubnetName) - ? { - customPublicSubnetName: { - value: customPublicSubnetName - } + } + : {}) + ...(!empty(customPrivateSubnetName) + ? { + customPrivateSubnetName: { + value: customPrivateSubnetName } - : {}, - !empty(loadBalancerBackendPoolName) - ? { - loadBalancerBackendPoolName: { - value: loadBalancerBackendPoolName - } + } + : {}) + ...(!empty(customPublicSubnetName) + ? { + customPublicSubnetName: { + value: customPublicSubnetName } - : {}, - !empty(loadBalancerResourceId) - ? { - loadBalancerId: { - value: loadBalancerResourceId - } + } + : {}) + ...(!empty(loadBalancerBackendPoolName) + ? { + loadBalancerBackendPoolName: { + value: loadBalancerBackendPoolName } - : {}, - !empty(natGatewayName) - ? { - natGatewayName: { - value: natGatewayName - } + } + : {}) + ...(!empty(loadBalancerResourceId) + ? { + loadBalancerId: { + value: loadBalancerResourceId } - : {}, - !empty(publicIpName) - ? { - publicIpName: { - value: publicIpName - } + } + : {}) + ...(!empty(natGatewayName) + ? { + natGatewayName: { + value: natGatewayName } - : {}, - !empty(storageAccountName) - ? { - storageAccountName: { - value: storageAccountName - } + } + : {}) + ...(!empty(publicIpName) + ? { + publicIpName: { + value: publicIpName } - : {}, - !empty(storageAccountSkuName) - ? { - storageAccountSkuName: { - value: storageAccountSkuName - } + } + : {}) + ...(!empty(storageAccountName) + ? { + storageAccountName: { + value: storageAccountName } - : {} - ) - // createdBy: {} // This is a read-only property - // managedDiskIdentity: {} // This is a read-only property - // storageAccountIdentity: {} // This is a read-only property - // updatedBy: {} // This is a read-only property - publicNetworkAccess: publicNetworkAccess - requiredNsgRules: requiredNsgRules - encryption: !empty(customerManagedKey) || !empty(customerManagedKeyManagedDisk) + } + : {}) + ...(!empty(storageAccountSkuName) ? { - entities: { - managedServices: !empty(customerManagedKey) - ? { - keySource: 'Microsoft.Keyvault' - keyVaultProperties: { - keyVaultUri: cMKKeyVault.properties.vaultUri - keyName: customerManagedKey!.keyName - keyVersion: !empty(customerManagedKey.?keyVersion ?? '') - ? customerManagedKey!.keyVersion! - : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) - } + storageAccountSkuName: { + value: storageAccountSkuName + } + } + : {}) + } + // createdBy: {} // This is a read-only property + // managedDiskIdentity: {} // This is a read-only property + // storageAccountIdentity: {} // This is a read-only property + // updatedBy: {} // This is a read-only property + publicNetworkAccess: publicNetworkAccess + requiredNsgRules: requiredNsgRules + encryption: !empty(customerManagedKey) || !empty(customerManagedKeyManagedDisk) + ? { + entities: { + managedServices: !empty(customerManagedKey) + ? { + keySource: 'Microsoft.Keyvault' + keyVaultProperties: { + keyVaultUri: cMKKeyVault.properties.vaultUri + keyName: customerManagedKey!.keyName + keyVersion: !empty(customerManagedKey.?keyVersion ?? '') + ? customerManagedKey!.keyVersion! + : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) } - : null - managedDisk: !empty(customerManagedKeyManagedDisk) - ? { - keySource: 'Microsoft.Keyvault' - keyVaultProperties: { - keyVaultUri: cMKManagedDiskKeyVault.properties.vaultUri - keyName: customerManagedKeyManagedDisk!.keyName - keyVersion: !empty(customerManagedKeyManagedDisk.?keyVersion ?? '') - ? customerManagedKeyManagedDisk!.keyVersion! - : last(split(cMKManagedDiskKeyVault::cMKKey.properties.keyUriWithVersion, '/')) - } - rotationToLatestKeyVersionEnabled: customerManagedKeyManagedDisk.?rotationToLatestKeyVersionEnabled ?? true + } + : null + managedDisk: !empty(customerManagedKeyManagedDisk) + ? { + keySource: 'Microsoft.Keyvault' + keyVaultProperties: { + keyVaultUri: cMKManagedDiskKeyVault.properties.vaultUri + keyName: customerManagedKeyManagedDisk!.keyName + keyVersion: !empty(customerManagedKeyManagedDisk.?keyVersion ?? '') + ? customerManagedKeyManagedDisk!.keyVersion! + : last(split(cMKManagedDiskKeyVault::cMKKey.properties.keyUriWithVersion, '/')) } - : null - } + rotationToLatestKeyVersionEnabled: customerManagedKeyManagedDisk.?rotationToLatestKeyVersionEnabled ?? true + } + : null } - : null - }, - !empty(privateStorageAccount) + } + : null + ...(!empty(privateStorageAccount) ? { defaultStorageFirewall: privateStorageAccount accessConnector: { @@ -358,16 +351,16 @@ resource workspace 'Microsoft.Databricks/workspaces@2024-05-01' = { identityType: 'SystemAssigned' } } - : {}, - !empty(defaultCatalog) + : {}) + ...(!empty(defaultCatalog) ? { defaultCatalog: { initialName: '' initialType: defaultCatalog.?initialType } } - : {}, - !empty(automaticClusterUpdate) || !empty(complianceStandards) || !empty(enhancedSecurityMonitoring) + : {}) + ...(!empty(automaticClusterUpdate) || !empty(complianceStandards) || !empty(enhancedSecurityMonitoring) ? { enhancedSecurityCompliance: { automaticClusterUpdate: { @@ -382,8 +375,8 @@ resource workspace 'Microsoft.Databricks/workspaces@2024-05-01' = { } } } - : {} - ) + : {}) + } } resource workspace_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { @@ -656,7 +649,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/databricks/workspace/main.json b/avm/res/databricks/workspace/main.json index 7d47a2361c..ab507bd0a7 100644 --- a/avm/res/databricks/workspace/main.json +++ b/avm/res/databricks/workspace/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "3097369557346474015" + "templateHash": "17989186567226192844" }, "name": "Azure Databricks Workspaces", "description": "This module deploys an Azure Databricks Workspace.", @@ -140,7 +140,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -879,7 +879,7 @@ "sku": { "name": "[parameters('skuName')]" }, - "properties": "[union(createObject('managedResourceGroupId', if(not(empty(parameters('managedResourceGroupResourceId'))), parameters('managedResourceGroupResourceId'), format('{0}/resourceGroups/rg-{1}-managed', subscription().id, parameters('name'))), 'parameters', union(createObject('enableNoPublicIp', createObject('value', parameters('disablePublicIp')), 'prepareEncryption', createObject('value', parameters('prepareEncryption')), 'vnetAddressPrefix', createObject('value', parameters('vnetAddressPrefix')), 'requireInfrastructureEncryption', createObject('value', parameters('requireInfrastructureEncryption'))), if(not(empty(parameters('customVirtualNetworkResourceId'))), createObject('customVirtualNetworkId', createObject('value', parameters('customVirtualNetworkResourceId'))), createObject()), if(not(empty(parameters('amlWorkspaceResourceId'))), createObject('amlWorkspaceId', createObject('value', parameters('amlWorkspaceResourceId'))), createObject()), if(not(empty(parameters('customPrivateSubnetName'))), createObject('customPrivateSubnetName', createObject('value', parameters('customPrivateSubnetName'))), createObject()), if(not(empty(parameters('customPublicSubnetName'))), createObject('customPublicSubnetName', createObject('value', parameters('customPublicSubnetName'))), createObject()), if(not(empty(parameters('loadBalancerBackendPoolName'))), createObject('loadBalancerBackendPoolName', createObject('value', parameters('loadBalancerBackendPoolName'))), createObject()), if(not(empty(parameters('loadBalancerResourceId'))), createObject('loadBalancerId', createObject('value', parameters('loadBalancerResourceId'))), createObject()), if(not(empty(parameters('natGatewayName'))), createObject('natGatewayName', createObject('value', parameters('natGatewayName'))), createObject()), if(not(empty(parameters('publicIpName'))), createObject('publicIpName', createObject('value', parameters('publicIpName'))), createObject()), if(not(empty(parameters('storageAccountName'))), createObject('storageAccountName', createObject('value', parameters('storageAccountName'))), createObject()), if(not(empty(parameters('storageAccountSkuName'))), createObject('storageAccountSkuName', createObject('value', parameters('storageAccountSkuName'))), createObject())), 'publicNetworkAccess', parameters('publicNetworkAccess'), 'requiredNsgRules', parameters('requiredNsgRules'), 'encryption', if(or(not(empty(parameters('customerManagedKey'))), not(empty(parameters('customerManagedKeyManagedDisk')))), createObject('entities', createObject('managedServices', if(not(empty(parameters('customerManagedKey'))), createObject('keySource', 'Microsoft.Keyvault', 'keyVaultProperties', createObject('keyVaultUri', reference('cMKKeyVault').vaultUri, 'keyName', parameters('customerManagedKey').keyName, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKey'), 'keyVersion'), ''))), parameters('customerManagedKey').keyVersion, last(split(reference('cMKKeyVault::cMKKey').keyUriWithVersion, '/'))))), null()), 'managedDisk', if(not(empty(parameters('customerManagedKeyManagedDisk'))), createObject('keySource', 'Microsoft.Keyvault', 'keyVaultProperties', createObject('keyVaultUri', reference('cMKManagedDiskKeyVault').vaultUri, 'keyName', parameters('customerManagedKeyManagedDisk').keyName, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVersion'), ''))), parameters('customerManagedKeyManagedDisk').keyVersion, last(split(reference('cMKManagedDiskKeyVault::cMKKey').keyUriWithVersion, '/')))), 'rotationToLatestKeyVersionEnabled', coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'rotationToLatestKeyVersionEnabled'), true())), null()))), null())), if(not(empty(parameters('privateStorageAccount'))), createObject('defaultStorageFirewall', parameters('privateStorageAccount'), 'accessConnector', createObject('id', parameters('accessConnectorResourceId'), 'identityType', 'SystemAssigned')), createObject()), if(not(empty(parameters('defaultCatalog'))), createObject('defaultCatalog', createObject('initialName', '', 'initialType', tryGet(parameters('defaultCatalog'), 'initialType'))), createObject()), if(or(or(not(empty(parameters('automaticClusterUpdate'))), not(empty(parameters('complianceStandards')))), not(empty(parameters('enhancedSecurityMonitoring')))), createObject('enhancedSecurityCompliance', createObject('automaticClusterUpdate', createObject('value', parameters('automaticClusterUpdate')), 'complianceSecurityProfile', createObject('complianceStandards', parameters('complianceStandards'), 'value', parameters('complianceSecurityProfileValue')), 'enhancedSecurityMonitoring', createObject('value', parameters('enhancedSecurityMonitoring')))), createObject()))]", + "properties": "[shallowMerge(createArray(createObject('managedResourceGroupId', if(not(empty(parameters('managedResourceGroupResourceId'))), parameters('managedResourceGroupResourceId'), format('{0}/resourceGroups/rg-{1}-managed', subscription().id, parameters('name'))), 'parameters', shallowMerge(createArray(createObject('enableNoPublicIp', createObject('value', parameters('disablePublicIp')), 'prepareEncryption', createObject('value', parameters('prepareEncryption')), 'vnetAddressPrefix', createObject('value', parameters('vnetAddressPrefix')), 'requireInfrastructureEncryption', createObject('value', parameters('requireInfrastructureEncryption'))), if(not(empty(parameters('customVirtualNetworkResourceId'))), createObject('customVirtualNetworkId', createObject('value', parameters('customVirtualNetworkResourceId'))), createObject()), if(not(empty(parameters('amlWorkspaceResourceId'))), createObject('amlWorkspaceId', createObject('value', parameters('amlWorkspaceResourceId'))), createObject()), if(not(empty(parameters('customPrivateSubnetName'))), createObject('customPrivateSubnetName', createObject('value', parameters('customPrivateSubnetName'))), createObject()), if(not(empty(parameters('customPublicSubnetName'))), createObject('customPublicSubnetName', createObject('value', parameters('customPublicSubnetName'))), createObject()), if(not(empty(parameters('loadBalancerBackendPoolName'))), createObject('loadBalancerBackendPoolName', createObject('value', parameters('loadBalancerBackendPoolName'))), createObject()), if(not(empty(parameters('loadBalancerResourceId'))), createObject('loadBalancerId', createObject('value', parameters('loadBalancerResourceId'))), createObject()), if(not(empty(parameters('natGatewayName'))), createObject('natGatewayName', createObject('value', parameters('natGatewayName'))), createObject()), if(not(empty(parameters('publicIpName'))), createObject('publicIpName', createObject('value', parameters('publicIpName'))), createObject()), if(not(empty(parameters('storageAccountName'))), createObject('storageAccountName', createObject('value', parameters('storageAccountName'))), createObject()), if(not(empty(parameters('storageAccountSkuName'))), createObject('storageAccountSkuName', createObject('value', parameters('storageAccountSkuName'))), createObject()))), 'publicNetworkAccess', parameters('publicNetworkAccess'), 'requiredNsgRules', parameters('requiredNsgRules'), 'encryption', if(or(not(empty(parameters('customerManagedKey'))), not(empty(parameters('customerManagedKeyManagedDisk')))), createObject('entities', createObject('managedServices', if(not(empty(parameters('customerManagedKey'))), createObject('keySource', 'Microsoft.Keyvault', 'keyVaultProperties', createObject('keyVaultUri', reference('cMKKeyVault').vaultUri, 'keyName', parameters('customerManagedKey').keyName, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKey'), 'keyVersion'), ''))), parameters('customerManagedKey').keyVersion, last(split(reference('cMKKeyVault::cMKKey').keyUriWithVersion, '/'))))), null()), 'managedDisk', if(not(empty(parameters('customerManagedKeyManagedDisk'))), createObject('keySource', 'Microsoft.Keyvault', 'keyVaultProperties', createObject('keyVaultUri', reference('cMKManagedDiskKeyVault').vaultUri, 'keyName', parameters('customerManagedKeyManagedDisk').keyName, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVersion'), ''))), parameters('customerManagedKeyManagedDisk').keyVersion, last(split(reference('cMKManagedDiskKeyVault::cMKKey').keyUriWithVersion, '/')))), 'rotationToLatestKeyVersionEnabled', coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'rotationToLatestKeyVersionEnabled'), true())), null()))), null())), if(not(empty(parameters('privateStorageAccount'))), createObject('defaultStorageFirewall', parameters('privateStorageAccount'), 'accessConnector', createObject('id', parameters('accessConnectorResourceId'), 'identityType', 'SystemAssigned')), createObject()), if(not(empty(parameters('defaultCatalog'))), createObject('defaultCatalog', createObject('initialName', '', 'initialType', tryGet(parameters('defaultCatalog'), 'initialType'))), createObject()), if(or(or(not(empty(parameters('automaticClusterUpdate'))), not(empty(parameters('complianceStandards')))), not(empty(parameters('enhancedSecurityMonitoring')))), createObject('enhancedSecurityCompliance', createObject('automaticClusterUpdate', createObject('value', parameters('automaticClusterUpdate')), 'complianceSecurityProfile', createObject('complianceStandards', parameters('complianceStandards'), 'value', parameters('complianceSecurityProfileValue')), 'enhancedSecurityMonitoring', createObject('value', parameters('enhancedSecurityMonitoring')))), createObject())))]", "dependsOn": [ "cMKKeyVault", "cMKManagedDiskKeyVault" diff --git a/avm/res/db-for-postgre-sql/flexible-server/README.md b/avm/res/db-for-postgre-sql/flexible-server/README.md index 5eacd67679..141436be5f 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/README.md +++ b/avm/res/db-for-postgre-sql/flexible-server/README.md @@ -23,8 +23,8 @@ This module deploys a DBforPostgreSQL Flexible Server. | `Microsoft.DBforPostgreSQL/flexibleServers/databases` | [2022-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DBforPostgreSQL/2022-12-01/flexibleServers/databases) | | `Microsoft.DBforPostgreSQL/flexibleServers/firewallRules` | [2022-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DBforPostgreSQL/2022-12-01/flexibleServers/firewallRules) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | -| `Microsoft.Network/privateEndpoints` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints) | -| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints/privateDnsZoneGroups) | +| `Microsoft.Network/privateEndpoints` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints) | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints/privateDnsZoneGroups) | ## Usage examples @@ -66,9 +66,6 @@ module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' } } ``` @@ -104,15 +101,6 @@ module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:" } } } @@ -140,9 +128,6 @@ param administrators = [ principalType: 'ServicePrincipal' } ] -param geoRedundantBackup = 'Enabled' -param highAvailability = 'ZoneRedundant' -param location = '' ``` @@ -162,7 +147,7 @@ module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' userAssignedIdentityResourceId: '' } + geoRedundantBackup: 'Disabled' location: '' managedIdentities: { userAssignedResourceIds: [ @@ -197,7 +183,7 @@ module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:" } }, + "geoRedundantBackup": { + "value": "Disabled" + }, "location": { "value": "" }, @@ -244,7 +233,7 @@ module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' // Required parameters -param name = 'dfpsfse001' +param name = 'dfpfmax001' param skuName = 'Standard_D2s_v3' param tier = 'GeneralPurpose' // Non-required parameters @@ -255,6 +244,7 @@ param customerManagedKey = { keyVaultResourceId: '' userAssignedIdentityResourceId: '' } +param geoRedundantBackup = 'Disabled' param location = '' param managedIdentities = { userAssignedResourceIds: [ @@ -580,9 +570,13 @@ module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' - ] + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: '' + } + ] + } subnetResourceId: '' tags: { Environment: 'Non-Prod' @@ -644,9 +638,13 @@ module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:" - ], + "privateDnsZoneGroup": { + "privateDnsZoneGroupConfigs": [ + { + "privateDnsZoneResourceId": "" + } + ] + }, "subnetResourceId": "", "tags": { "Environment": "Non-Prod", @@ -688,9 +686,13 @@ param maintenanceWindow = { } param privateEndpoints = [ { - privateDnsZoneResourceIds: [ - '' - ] + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: '' + } + ] + } subnetResourceId: '' tags: { Environment: 'Non-Prod' @@ -1104,7 +1106,6 @@ module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' } ] - geoRedundantBackup: 'Enabled' highAvailability: 'ZoneRedundant' location: '' maintenanceWindow: { @@ -1194,9 +1195,6 @@ module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' } ] -param geoRedundantBackup = 'Enabled' param highAvailability = 'ZoneRedundant' param location = '' param maintenanceWindow = { @@ -1320,8 +1317,7 @@ param tags = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`activeDirectoryAuth`](#parameter-activedirectoryauth) | string | If Enabled, Azure Active Directory authentication is enabled. | -| [`administratorLogin`](#parameter-administratorlogin) | string | The administrator login name of a server. Can only be specified when the PostgreSQL server is being created. | +| [`administratorLogin`](#parameter-administratorlogin) | string | The administrator login name for the server. Can only be specified when the PostgreSQL server is being created. | | [`administratorLoginPassword`](#parameter-administratorloginpassword) | securestring | The administrator login password. | | [`administrators`](#parameter-administrators) | array | The Azure AD administrators when AAD authentication enabled. | | [`availabilityZone`](#parameter-availabilityzone) | string | Availability zone information of the server. Default will have no preference set. | @@ -1334,12 +1330,11 @@ param tags = { | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`firewallRules`](#parameter-firewallrules) | array | The firewall rules to create in the PostgreSQL flexible server. | -| [`geoRedundantBackup`](#parameter-georedundantbackup) | string | A value indicating whether Geo-Redundant backup is enabled on the server. Should be left disabled if 'cMKKeyName' is not empty. | +| [`geoRedundantBackup`](#parameter-georedundantbackup) | string | A value indicating whether Geo-Redundant backup is enabled on the server. Should be disabled if 'cMKKeyName' is not empty. | | [`highAvailability`](#parameter-highavailability) | string | The mode for high availability. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`maintenanceWindow`](#parameter-maintenancewindow) | object | Properties for the maintenence window. If provided, 'customWindow' property must exist and set to 'Enabled'. | -| [`passwordAuth`](#parameter-passwordauth) | string | If Enabled, password authentication is enabled. | | [`privateDnsZoneArmResourceId`](#parameter-privatednszonearmresourceid) | string | Private dns zone arm resource ID. Used when the desired connectivity mode is 'Private Access' and required when 'delegatedSubnetResourceId' is used. The Private DNS Zone must be linked to the Virtual Network referenced in 'delegatedSubnetResourceId'. | | [`privateEndpoints`](#parameter-privateendpoints) | array | Configuration details for private endpoints. Used when the desired connectivy mode is 'Public Access' and 'delegatedSubnetResourceId' is NOT used. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | @@ -1388,13 +1383,13 @@ The managed identity definition for this resource. Required if 'cMKKeyName' is n | Parameter | Type | Description | | :-- | :-- | :-- | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | ### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. -- Required: Yes +- Required: No - Type: array ### Parameter: `pointInTimeUTC` @@ -1413,28 +1408,12 @@ Required if 'createMode' is set to 'PointInTimeRestore'. - Type: string - Default: `''` -### Parameter: `activeDirectoryAuth` - -If Enabled, Azure Active Directory authentication is enabled. - -- Required: No -- Type: string -- Default: `'Enabled'` -- Allowed: - ```Bicep - [ - 'Disabled' - 'Enabled' - ] - ``` - ### Parameter: `administratorLogin` -The administrator login name of a server. Can only be specified when the PostgreSQL server is being created. +The administrator login name for the server. Can only be specified when the PostgreSQL server is being created. - Required: No - Type: string -- Default: `''` ### Parameter: `administratorLoginPassword` @@ -1442,7 +1421,6 @@ The administrator login password. - Required: No - Type: securestring -- Default: `''` ### Parameter: `administrators` @@ -1497,7 +1475,9 @@ The mode to create a new PostgreSQL server. [ 'Create' 'Default' + 'GeoRestore' 'PointInTimeRestore' + 'Replica' 'Update' ] ``` @@ -1515,13 +1495,13 @@ The customer managed key definition. | :-- | :-- | :-- | | [`keyName`](#parameter-customermanagedkeykeyname) | string | The name of the customer managed key to use for encryption. | | [`keyVaultResourceId`](#parameter-customermanagedkeykeyvaultresourceid) | string | The resource ID of a key vault to reference a customer managed key for encryption from. | -| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeyuserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. | **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | | [`keyVersion`](#parameter-customermanagedkeykeyversion) | string | The version of the customer managed key to reference for encryption. If not provided, using 'latest'. | +| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeyuserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. | ### Parameter: `customerManagedKey.keyName` @@ -1537,16 +1517,16 @@ The resource ID of a key vault to reference a customer managed key for encryptio - Required: Yes - Type: string -### Parameter: `customerManagedKey.userAssignedIdentityResourceId` +### Parameter: `customerManagedKey.keyVersion` -User assigned identity to use when fetching the customer managed key. +The version of the customer managed key to reference for encryption. If not provided, using 'latest'. -- Required: Yes +- Required: No - Type: string -### Parameter: `customerManagedKey.keyVersion` +### Parameter: `customerManagedKey.userAssignedIdentityResourceId` -The version of the customer managed key to reference for encryption. If not provided, using 'latest'. +User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. - Required: No - Type: string @@ -1584,7 +1564,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -1694,7 +1674,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -1731,11 +1711,11 @@ The firewall rules to create in the PostgreSQL flexible server. ### Parameter: `geoRedundantBackup` -A value indicating whether Geo-Redundant backup is enabled on the server. Should be left disabled if 'cMKKeyName' is not empty. +A value indicating whether Geo-Redundant backup is enabled on the server. Should be disabled if 'cMKKeyName' is not empty. - Required: No - Type: string -- Default: `'Disabled'` +- Default: `'Enabled'` - Allowed: ```Bicep [ @@ -1820,21 +1800,6 @@ Properties for the maintenence window. If provided, 'customWindow' property must } ``` -### Parameter: `passwordAuth` - -If Enabled, password authentication is enabled. - -- Required: No -- Type: string -- Default: `'Disabled'` -- Allowed: - ```Bicep - [ - 'Disabled' - 'Enabled' - ] - ``` - ### Parameter: `privateDnsZoneArmResourceId` Private dns zone arm resource ID. Used when the desired connectivity mode is 'Private Access' and required when 'delegatedSubnetResourceId' is used. The Private DNS Zone must be linked to the Virtual Network referenced in 'delegatedSubnetResourceId'. @@ -1860,23 +1825,22 @@ Configuration details for private endpoints. Used when the desired connectivy mo | Parameter | Type | Description | | :-- | :-- | :-- | -| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the Private Endpoint IP configuration is included. | | [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | -| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the Private Endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. | | [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | -| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the Private Endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | -| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. | -| [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | +| [`name`](#parameter-privateendpointsname) | string | The name of the Private Endpoint. | +| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS Zone Group to configure for the Private Endpoint. | | [`privateLinkServiceConnectionName`](#parameter-privateendpointsprivatelinkserviceconnectionname) | string | The name of the private link connection to create. | -| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. | +| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | -| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/Resource Groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -1887,7 +1851,7 @@ Resource ID of the subnet where the endpoint needs to be created. ### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` -Application security groups in which the private endpoint IP configuration is included. +Application security groups in which the Private Endpoint IP configuration is included. - Required: No - Type: array @@ -1903,15 +1867,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1920,9 +1882,16 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` -The custom name of the network interface attached to the private endpoint. +The custom name of the network interface attached to the Private Endpoint. - Required: No - Type: string @@ -1936,7 +1905,7 @@ Enable/Disable usage telemetry for module. ### Parameter: `privateEndpoints.ipConfigurations` -A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. +A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. - Required: No - Type: array @@ -2000,7 +1969,7 @@ If Manual Private Link Connection is required. ### Parameter: `privateEndpoints.location` -The location to deploy the private endpoint to. +The location to deploy the Private Endpoint to. - Required: No - Type: string @@ -2050,24 +2019,69 @@ A message passed to the owner of the remote resource with the manual connection ### Parameter: `privateEndpoints.name` -The name of the private endpoint. +The name of the Private Endpoint. - Required: No - Type: string -### Parameter: `privateEndpoints.privateDnsZoneGroupName` +### Parameter: `privateEndpoints.privateDnsZoneGroup` + +The private DNS Zone Group to configure for the Private Endpoint. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the Private DNS Zone Group. | + +### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` + +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. + +- Required: Yes +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`privateDnsZoneResourceId`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsprivatednszoneresourceid) | string | The resource id of the private DNS zone. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | + +### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` + +The resource id of the private DNS zone. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. +The name of the private DNS Zone Group config. - Required: No - Type: string -### Parameter: `privateEndpoints.privateDnsZoneResourceIds` +### Parameter: `privateEndpoints.privateDnsZoneGroup.name` -The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. +The name of the Private DNS Zone Group. - Required: No -- Type: array +- Type: string ### Parameter: `privateEndpoints.privateLinkServiceConnectionName` @@ -2078,7 +2092,7 @@ The name of the private link connection to create. ### Parameter: `privateEndpoints.resourceGroupName` -Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. +Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. - Required: No - Type: string @@ -2099,7 +2113,7 @@ Array of role assignments to create. - `'Owner'` - `'Private DNS Zone Contributor'` - `'Reader'` - - `'Role Based Access Control Administrator (Preview)'` + - `'Role Based Access Control Administrator'` **Required parameters** @@ -2193,14 +2207,14 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". +The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.tags` -Tags to be applied on all resources/resource groups in this deployment. +Tags to be applied on all resources/Resource Groups in this deployment. - Required: No - Type: object @@ -2344,7 +2358,6 @@ Tenant id of the server. - Required: No - Type: string -- Default: `''` ### Parameter: `version` @@ -2381,7 +2394,8 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/private-endpoint:0.4.1` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.8.0` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/db-for-postgre-sql/flexible-server/administrator/main.json b/avm/res/db-for-postgre-sql/flexible-server/administrator/main.json index b7337b4766..83f8bcd344 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/administrator/main.json +++ b/avm/res/db-for-postgre-sql/flexible-server/administrator/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9786947819042824705" + "version": "0.31.34.60546", + "templateHash": "16481538210870485841" }, "name": "DBforPostgreSQL Flexible Server Administrators", "description": "This module deploys a DBforPostgreSQL Flexible Server Administrator.", diff --git a/avm/res/db-for-postgre-sql/flexible-server/configuration/README.md b/avm/res/db-for-postgre-sql/flexible-server/configuration/README.md index f300edd81a..9f49570060 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/configuration/README.md +++ b/avm/res/db-for-postgre-sql/flexible-server/configuration/README.md @@ -55,7 +55,6 @@ Source of the configuration. - Required: No - Type: string -- Default: `''` ### Parameter: `value` @@ -63,7 +62,6 @@ Value of the configuration. - Required: No - Type: string -- Default: `''` ## Outputs diff --git a/avm/res/db-for-postgre-sql/flexible-server/configuration/main.bicep b/avm/res/db-for-postgre-sql/flexible-server/configuration/main.bicep index 1a883000e9..e98529bda5 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/configuration/main.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/configuration/main.bicep @@ -9,10 +9,10 @@ param name string param flexibleServerName string @description('Optional. Source of the configuration.') -param source string = '' +param source string? @description('Optional. Value of the configuration.') -param value string = '' +param value string? resource flexibleServer 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' existing = { name: flexibleServerName diff --git a/avm/res/db-for-postgre-sql/flexible-server/configuration/main.json b/avm/res/db-for-postgre-sql/flexible-server/configuration/main.json index 8903e9ef21..4026bdbe02 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/configuration/main.json +++ b/avm/res/db-for-postgre-sql/flexible-server/configuration/main.json @@ -1,11 +1,12 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "3802666632340288344" + "version": "0.31.34.60546", + "templateHash": "4744350024962623928" }, "name": "DBforPostgreSQL Flexible Server Configurations", "description": "This module deploys a DBforPostgreSQL Flexible Server Configuration.", @@ -26,21 +27,27 @@ }, "source": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Source of the configuration." } }, "value": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Value of the configuration." } } }, - "resources": [ - { + "resources": { + "flexibleServer": { + "existing": true, + "type": "Microsoft.DBforPostgreSQL/flexibleServers", + "apiVersion": "2022-12-01", + "name": "[parameters('flexibleServerName')]" + }, + "configuration": { "type": "Microsoft.DBforPostgreSQL/flexibleServers/configurations", "apiVersion": "2022-12-01", "name": "[format('{0}/{1}', parameters('flexibleServerName'), parameters('name'))]", @@ -49,7 +56,7 @@ "value": "[if(not(empty(parameters('value'))), parameters('value'), null())]" } } - ], + }, "outputs": { "name": { "type": "string", diff --git a/avm/res/db-for-postgre-sql/flexible-server/database/README.md b/avm/res/db-for-postgre-sql/flexible-server/database/README.md index 230fce3117..021848ff39 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/database/README.md +++ b/avm/res/db-for-postgre-sql/flexible-server/database/README.md @@ -55,7 +55,6 @@ The charset of the database. - Required: No - Type: string -- Default: `''` ### Parameter: `collation` @@ -63,7 +62,6 @@ The collation of the database. - Required: No - Type: string -- Default: `''` ## Outputs diff --git a/avm/res/db-for-postgre-sql/flexible-server/database/main.bicep b/avm/res/db-for-postgre-sql/flexible-server/database/main.bicep index 3e5cbdf09b..761f57e376 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/database/main.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/database/main.bicep @@ -9,10 +9,10 @@ param name string param flexibleServerName string @description('Optional. The collation of the database.') -param collation string = '' +param collation string? @description('Optional. The charset of the database.') -param charset string = '' +param charset string? resource flexibleServer 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' existing = { name: flexibleServerName diff --git a/avm/res/db-for-postgre-sql/flexible-server/database/main.json b/avm/res/db-for-postgre-sql/flexible-server/database/main.json index 1b15b5c7a4..3009f6fc24 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/database/main.json +++ b/avm/res/db-for-postgre-sql/flexible-server/database/main.json @@ -1,11 +1,12 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17501165975344742322" + "version": "0.31.34.60546", + "templateHash": "5925943942284222024" }, "name": "DBforPostgreSQL Flexible Server Databases", "description": "This module deploys a DBforPostgreSQL Flexible Server Database.", @@ -26,21 +27,27 @@ }, "collation": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The collation of the database." } }, "charset": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The charset of the database." } } }, - "resources": [ - { + "resources": { + "flexibleServer": { + "existing": true, + "type": "Microsoft.DBforPostgreSQL/flexibleServers", + "apiVersion": "2022-12-01", + "name": "[parameters('flexibleServerName')]" + }, + "database": { "type": "Microsoft.DBforPostgreSQL/flexibleServers/databases", "apiVersion": "2022-12-01", "name": "[format('{0}/{1}', parameters('flexibleServerName'), parameters('name'))]", @@ -49,7 +56,7 @@ "charset": "[if(not(empty(parameters('charset'))), parameters('charset'), null())]" } } - ], + }, "outputs": { "name": { "type": "string", diff --git a/avm/res/db-for-postgre-sql/flexible-server/firewall-rule/main.json b/avm/res/db-for-postgre-sql/flexible-server/firewall-rule/main.json index 572f886bfe..4db73ef457 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/firewall-rule/main.json +++ b/avm/res/db-for-postgre-sql/flexible-server/firewall-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5110779562094536429" + "version": "0.31.34.60546", + "templateHash": "9983440066171652627" }, "name": "DBforPostgreSQL Flexible Server Firewall Rules", "description": "This module deploys a DBforPostgreSQL Flexible Server Firewall Rule.", diff --git a/avm/res/db-for-postgre-sql/flexible-server/main.bicep b/avm/res/db-for-postgre-sql/flexible-server/main.bicep index c2cd387401..b0488e73f0 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/main.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/main.bicep @@ -5,30 +5,15 @@ metadata owner = 'Azure/module-maintainers' @description('Required. The name of the PostgreSQL flexible server.') param name string -@description('Optional. The administrator login name of a server. Can only be specified when the PostgreSQL server is being created.') -param administratorLogin string = '' +@description('Optional. The administrator login name for the server. Can only be specified when the PostgreSQL server is being created.') +param administratorLogin string? @description('Optional. The administrator login password.') @secure() -param administratorLoginPassword string = '' - -@allowed([ - 'Disabled' - 'Enabled' -]) -@description('Optional. If Enabled, Azure Active Directory authentication is enabled.') -param activeDirectoryAuth string = 'Enabled' - -@allowed([ - 'Disabled' - 'Enabled' -]) -@description('Optional. If Enabled, password authentication is enabled.') -#disable-next-line secure-secrets-in-params -param passwordAuth string = 'Disabled' +param administratorLoginPassword string? @description('Optional. Tenant id of the server.') -param tenantId string = '' +param tenantId string? @description('Optional. The Azure AD administrators when AAD authentication enabled.') param administrators array = [] @@ -65,8 +50,8 @@ param backupRetentionDays int = 7 'Disabled' 'Enabled' ]) -@description('Optional. A value indicating whether Geo-Redundant backup is enabled on the server. Should be left disabled if \'cMKKeyName\' is not empty.') -param geoRedundantBackup string = 'Disabled' +@description('Optional. A value indicating whether Geo-Redundant backup is enabled on the server. Should be disabled if \'cMKKeyName\' is not empty.') +param geoRedundantBackup string = 'Enabled' // Enabled by default for WAF-alignment (ref: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.PostgreSQL.GeoRedundantBackup/) @allowed([ 32 @@ -105,17 +90,21 @@ param highAvailability string = 'ZoneRedundant' @allowed([ 'Create' 'Default' + 'GeoRestore' 'PointInTimeRestore' + 'Replica' 'Update' ]) @description('Optional. The mode to create a new PostgreSQL server.') param createMode string = 'Default' +import { managedIdentityOnlyUserAssignedType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Conditional. The managed identity definition for this resource. Required if \'cMKKeyName\' is not empty.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityOnlyUserAssignedType? +import { customerManagedKeyType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The customer managed key definition.') -param customerManagedKey customerManagedKeyType +param customerManagedKey customerManagedKeyType? @description('Optional. Properties for the maintenence window. If provided, \'customWindow\' property must exist and set to \'Enabled\'.') param maintenanceWindow object = { @@ -146,11 +135,13 @@ param databases array = [] @description('Optional. The configurations to create in the server.') param configurations array = [] +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the resource.') param tags object? @@ -158,11 +149,13 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. Used when the desired connectivy mode is \'Public Access\' and \'delegatedSubnetResourceId\' is NOT used.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointSingleServiceType[]? var formattedUserAssignedIdentities = reduce( map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), @@ -251,12 +244,12 @@ resource flexibleServer 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' = } identity: identity properties: { - administratorLogin: !empty(administratorLogin) ? administratorLogin : null - administratorLoginPassword: !empty(administratorLoginPassword) ? administratorLoginPassword : null + administratorLogin: administratorLogin + administratorLoginPassword: administratorLoginPassword authConfig: { - activeDirectoryAuth: activeDirectoryAuth - passwordAuth: passwordAuth - tenantId: !empty(tenantId) ? tenantId : null + activeDirectoryAuth: !empty(administrators) ? 'enabled' : 'disabled' + passwordAuth: !empty(administratorLogin) && !empty(administratorLoginPassword) ? 'enabled' : 'disabled' + tenantId: tenantId } availabilityZone: availabilityZone backup: { @@ -292,7 +285,9 @@ resource flexibleServer 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' = } : null pointInTimeUTC: createMode == 'PointInTimeRestore' ? pointInTimeUTC : null - sourceServerResourceId: createMode == 'PointInTimeRestore' ? sourceServerResourceId : null + sourceServerResourceId: (createMode == 'PointInTimeRestore' || createMode == 'Replica') + ? sourceServerResourceId + : null storage: { storageSizeGB: storageSizeGB } @@ -333,8 +328,8 @@ module flexibleServer_databases 'database/main.bicep' = [ params: { name: database.name flexibleServerName: flexibleServer.name - collation: database.?collation ?? '' - charset: database.?charset ?? '' + collation: database.?collation + charset: database.?charset } } ] @@ -361,8 +356,8 @@ module flexibleServer_configurations 'configuration/main.bicep' = [ params: { name: configuration.name flexibleServerName: flexibleServer.name - source: configuration.?source ?? '' - value: configuration.?value ?? '' + source: configuration.?source + value: configuration.?value } dependsOn: [ flexibleServer_firewallRules @@ -378,7 +373,7 @@ module flexibleServer_administrators 'administrator/main.bicep' = [ objectId: administrator.objectId principalName: administrator.principalName principalType: administrator.principalType - tenantId: administrator.?tenantId ?? tenant().tenantId + tenantId: administrator.?tenantId } dependsOn: [ flexibleServer_configurations @@ -415,9 +410,9 @@ resource flexibleServer_diagnosticSettings 'Microsoft.Insights/diagnosticSetting } ] -module server_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ +module server_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.8.0' = [ for (privateEndpoint, index) in (privateEndpoints ?? []): if (empty(delegatedSubnetResourceId)) { - name: '${uniqueString(deployment().name, location)}-flexibleserver-PrivateEndpoint-${index}' + name: '${uniqueString(deployment().name, location)}-PostgreSQL-PrivateEndpoint-${index}' scope: resourceGroup(privateEndpoint.?resourceGroupName ?? '') params: { name: privateEndpoint.?name ?? 'pep-${last(split(flexibleServer.id, '/'))}-${privateEndpoint.?service ?? 'postgresqlServer'}-${index}' @@ -456,8 +451,7 @@ module server_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1 'Full' ).location lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags customDnsConfigs: privateEndpoint.?customDnsConfigs @@ -482,182 +476,3 @@ output location string = flexibleServer.location @description('The FQDN of the PostgreSQL Flexible server.') output fqdn string = flexibleServer.properties.fullyQualifiedDomainName - -// =============== // -// Definitions // -// =============== // - -type managedIdentitiesType = { - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[] -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? - -type customerManagedKeyType = { - @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') - keyVaultResourceId: string - - @description('Required. The name of the customer managed key to use for encryption.') - keyName: string - - @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') - keyVersion: string? - - @description('Required. User assigned identity to use when fetching the customer managed key.') - userAssignedIdentityResourceId: string -}? - -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') - service: string? - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided.') - privateDnsZoneGroupName: string? - - @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneResourceIds: string[]? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? - - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? diff --git a/avm/res/db-for-postgre-sql/flexible-server/main.json b/avm/res/db-for-postgre-sql/flexible-server/main.json index fde16d696e..5df3bdd416 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/main.json +++ b/avm/res/db-for-postgre-sql/flexible-server/main.json @@ -5,28 +5,281 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "17059388834695026761" + "version": "0.31.34.60546", + "templateHash": "13236500116916645585" }, "name": "DBforPostgreSQL Flexible Servers", "description": "This module deploys a DBforPostgreSQL Flexible Server.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { + "_1.privateEndpointCustomDnsConfigType": { "type": "object", "properties": { - "userAssignedResourceIds": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { "type": "array", "items": { "type": "string" }, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Required. A list of private IP addresses of the private endpoint." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS Zone Group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a customer-managed key.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "lockType": { "type": "object", @@ -51,428 +304,250 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } + "managedIdentityOnlyUserAssignedType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } + "privateEndpointSingleServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private Endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the Private Endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the Private Endpoint for. For example \"vault\" for a Key Vault Private Endpoint." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS Zone Group to configure for the Private Endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the Private Endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the Private Endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/Resource Groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like 'vault' for key vault).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." } - } - }, - "nullable": true - }, - "customerManagedKeyType": { - "type": "object", - "properties": { - "keyVaultResourceId": { + }, + "description": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + "description": "Optional. The description of the role assignment." } }, - "keyName": { + "condition": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The name of the customer managed key to use for encryption." + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." } }, - "keyVersion": { + "conditionVersion": { "type": "string", + "allowedValues": [ + "2.0" + ], "nullable": true, "metadata": { - "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + "description": "Optional. Version of the condition." } }, - "userAssignedIdentityResourceId": { + "delegatedManagedIdentityResourceId": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. User assigned identity to use when fetching the customer managed key." + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true - }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." - } - }, - "privateDnsZoneGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." - } - }, - "privateDnsZoneResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } - }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } - } + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" } - }, - "nullable": true + } } }, "parameters": { @@ -484,43 +559,21 @@ }, "administratorLogin": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { - "description": "Optional. The administrator login name of a server. Can only be specified when the PostgreSQL server is being created." + "description": "Optional. The administrator login name for the server. Can only be specified when the PostgreSQL server is being created." } }, "administratorLoginPassword": { "type": "securestring", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The administrator login password." } }, - "activeDirectoryAuth": { - "type": "string", - "defaultValue": "Enabled", - "allowedValues": [ - "Disabled", - "Enabled" - ], - "metadata": { - "description": "Optional. If Enabled, Azure Active Directory authentication is enabled." - } - }, - "passwordAuth": { - "type": "string", - "defaultValue": "Disabled", - "allowedValues": [ - "Disabled", - "Enabled" - ], - "metadata": { - "description": "Optional. If Enabled, password authentication is enabled." - } - }, "tenantId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Tenant id of the server." } @@ -580,13 +633,13 @@ }, "geoRedundantBackup": { "type": "string", - "defaultValue": "Disabled", + "defaultValue": "Enabled", "allowedValues": [ "Disabled", "Enabled" ], "metadata": { - "description": "Optional. A value indicating whether Geo-Redundant backup is enabled on the server. Should be left disabled if 'cMKKeyName' is not empty." + "description": "Optional. A value indicating whether Geo-Redundant backup is enabled on the server. Should be disabled if 'cMKKeyName' is not empty." } }, "storageSizeGB": { @@ -641,7 +694,9 @@ "allowedValues": [ "Create", "Default", + "GeoRestore", "PointInTimeRestore", + "Replica", "Update" ], "metadata": { @@ -649,13 +704,15 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityOnlyUserAssignedType", + "nullable": true, "metadata": { "description": "Conditional. The managed identity definition for this resource. Required if 'cMKKeyName' is not empty." } }, "customerManagedKey": { "$ref": "#/definitions/customerManagedKeyType", + "nullable": true, "metadata": { "description": "Optional. The customer managed key definition." } @@ -723,12 +780,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -748,13 +810,21 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointSingleServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. Used when the desired connectivy mode is 'Public Access' and 'delegatedSubnetResourceId' is NOT used." } @@ -786,10 +856,7 @@ "apiVersion": "2023-07-01", "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", - "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKey'), 'keyName'), 'dummyKey'))]", - "dependsOn": [ - "cMKKeyVault" - ] + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKey'), 'keyName'), 'dummyKey'))]" }, "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", @@ -841,12 +908,12 @@ }, "identity": "[variables('identity')]", "properties": { - "administratorLogin": "[if(not(empty(parameters('administratorLogin'))), parameters('administratorLogin'), null())]", - "administratorLoginPassword": "[if(not(empty(parameters('administratorLoginPassword'))), parameters('administratorLoginPassword'), null())]", + "administratorLogin": "[parameters('administratorLogin')]", + "administratorLoginPassword": "[parameters('administratorLoginPassword')]", "authConfig": { - "activeDirectoryAuth": "[parameters('activeDirectoryAuth')]", - "passwordAuth": "[parameters('passwordAuth')]", - "tenantId": "[if(not(empty(parameters('tenantId'))), parameters('tenantId'), null())]" + "activeDirectoryAuth": "[if(not(empty(parameters('administrators'))), 'enabled', 'disabled')]", + "passwordAuth": "[if(and(not(empty(parameters('administratorLogin'))), not(empty(parameters('administratorLoginPassword')))), 'enabled', 'disabled')]", + "tenantId": "[parameters('tenantId')]" }, "availabilityZone": "[parameters('availabilityZone')]", "backup": { @@ -862,16 +929,12 @@ "maintenanceWindow": "[if(not(empty(parameters('maintenanceWindow'))), createObject('customWindow', parameters('maintenanceWindow').customWindow, 'dayOfWeek', if(equals(parameters('maintenanceWindow').customWindow, 'Enabled'), parameters('maintenanceWindow').dayOfWeek, 0), 'startHour', if(equals(parameters('maintenanceWindow').customWindow, 'Enabled'), parameters('maintenanceWindow').startHour, 0), 'startMinute', if(equals(parameters('maintenanceWindow').customWindow, 'Enabled'), parameters('maintenanceWindow').startMinute, 0)), null())]", "network": "[if(and(not(empty(parameters('delegatedSubnetResourceId'))), empty(parameters('firewallRules'))), createObject('delegatedSubnetResourceId', parameters('delegatedSubnetResourceId'), 'privateDnsZoneArmResourceId', parameters('privateDnsZoneArmResourceId')), null())]", "pointInTimeUTC": "[if(equals(parameters('createMode'), 'PointInTimeRestore'), parameters('pointInTimeUTC'), null())]", - "sourceServerResourceId": "[if(equals(parameters('createMode'), 'PointInTimeRestore'), parameters('sourceServerResourceId'), null())]", + "sourceServerResourceId": "[if(or(equals(parameters('createMode'), 'PointInTimeRestore'), equals(parameters('createMode'), 'Replica')), parameters('sourceServerResourceId'), null())]", "storage": { "storageSizeGB": "[parameters('storageSizeGB')]" }, "version": "[parameters('version')]" - }, - "dependsOn": [ - "cMKKeyVault", - "cMKUserAssignedIdentity" - ] + } }, "flexibleServer_lock": { "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", @@ -971,20 +1034,21 @@ "value": "[parameters('name')]" }, "collation": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'collation'), '')]" + "value": "[tryGet(parameters('databases')[copyIndex()], 'collation')]" }, "charset": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'charset'), '')]" + "value": "[tryGet(parameters('databases')[copyIndex()], 'charset')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "6060199938382421423" + "version": "0.31.34.60546", + "templateHash": "5925943942284222024" }, "name": "DBforPostgreSQL Flexible Server Databases", "description": "This module deploys a DBforPostgreSQL Flexible Server Database.", @@ -1005,21 +1069,27 @@ }, "collation": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The collation of the database." } }, "charset": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The charset of the database." } } }, - "resources": [ - { + "resources": { + "flexibleServer": { + "existing": true, + "type": "Microsoft.DBforPostgreSQL/flexibleServers", + "apiVersion": "2022-12-01", + "name": "[parameters('flexibleServerName')]" + }, + "database": { "type": "Microsoft.DBforPostgreSQL/flexibleServers/databases", "apiVersion": "2022-12-01", "name": "[format('{0}/{1}', parameters('flexibleServerName'), parameters('name'))]", @@ -1028,7 +1098,7 @@ "charset": "[if(not(empty(parameters('charset'))), parameters('charset'), null())]" } } - ], + }, "outputs": { "name": { "type": "string", @@ -1091,8 +1161,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "18047073594923038356" + "version": "0.31.34.60546", + "templateHash": "9983440066171652627" }, "name": "DBforPostgreSQL Flexible Server Firewall Rules", "description": "This module deploys a DBforPostgreSQL Flexible Server Firewall Rule.", @@ -1188,20 +1258,21 @@ "value": "[parameters('name')]" }, "source": { - "value": "[coalesce(tryGet(parameters('configurations')[copyIndex()], 'source'), '')]" + "value": "[tryGet(parameters('configurations')[copyIndex()], 'source')]" }, "value": { - "value": "[coalesce(tryGet(parameters('configurations')[copyIndex()], 'value'), '')]" + "value": "[tryGet(parameters('configurations')[copyIndex()], 'value')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "1739518705583408324" + "version": "0.31.34.60546", + "templateHash": "4744350024962623928" }, "name": "DBforPostgreSQL Flexible Server Configurations", "description": "This module deploys a DBforPostgreSQL Flexible Server Configuration.", @@ -1222,21 +1293,27 @@ }, "source": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Source of the configuration." } }, "value": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Value of the configuration." } } }, - "resources": [ - { + "resources": { + "flexibleServer": { + "existing": true, + "type": "Microsoft.DBforPostgreSQL/flexibleServers", + "apiVersion": "2022-12-01", + "name": "[parameters('flexibleServerName')]" + }, + "configuration": { "type": "Microsoft.DBforPostgreSQL/flexibleServers/configurations", "apiVersion": "2022-12-01", "name": "[format('{0}/{1}', parameters('flexibleServerName'), parameters('name'))]", @@ -1245,7 +1322,7 @@ "value": "[if(not(empty(parameters('value'))), parameters('value'), null())]" } } - ], + }, "outputs": { "name": { "type": "string", @@ -1303,7 +1380,7 @@ "value": "[parameters('administrators')[copyIndex()].principalType]" }, "tenantId": { - "value": "[coalesce(tryGet(parameters('administrators')[copyIndex()], 'tenantId'), tenant().tenantId)]" + "value": "[tryGet(parameters('administrators')[copyIndex()], 'tenantId')]" } }, "template": { @@ -1312,8 +1389,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "18164580138640455419" + "version": "0.31.34.60546", + "templateHash": "16481538210870485841" }, "name": "DBforPostgreSQL Flexible Server Administrators", "description": "This module deploys a DBforPostgreSQL Flexible Server Administrator.", @@ -1408,7 +1485,7 @@ "condition": "[empty(parameters('delegatedSubnetResourceId'))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-flexibleserver-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "name": "[format('{0}-PostgreSQL-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "resourceGroup": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'resourceGroupName'), '')]", "properties": { "expressionEvaluationOptions": { @@ -1433,11 +1510,8 @@ "lock": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" }, - "privateDnsZoneGroupName": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" - }, - "privateDnsZoneResourceIds": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + "privateDnsZoneGroup": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" }, "roleAssignments": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" @@ -1465,19 +1539,47 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4120048060064073955" + "version": "0.29.47.4906", + "templateHash": "10193943972635711937" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", "owner": "Azure/module-maintainers" }, "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, "roleAssignmentType": { "type": "array", "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -1581,13 +1683,13 @@ "groupId": { "type": "string", "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." } }, "memberName": { "type": "string", "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." } }, "privateIPAddress": { @@ -1621,8 +1723,11 @@ "properties": { "groupIds": { "type": "array", + "items": { + "type": "string" + }, "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." } }, "privateLinkServiceId": { @@ -1662,8 +1767,11 @@ "properties": { "groupIds": { "type": "array", + "items": { + "type": "string" + }, "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." } }, "privateLinkServiceId": { @@ -1711,6 +1819,29 @@ } }, "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } } }, "parameters": { @@ -1746,18 +1877,11 @@ "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } }, - "privateDnsZoneGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." - } - }, - "privateDnsZoneResourceIds": { - "type": "array", + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", "nullable": true, "metadata": { - "description": "Optional. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + "description": "Optional. The private DNS zone group to configure for the private endpoint." } }, "location": { @@ -1813,6 +1937,13 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", @@ -1823,15 +1954,15 @@ "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" } }, "resources": { "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.8.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1849,7 +1980,7 @@ }, "privateEndpoint": { "type": "Microsoft.Network/privateEndpoints", - "apiVersion": "2023-04-01", + "apiVersion": "2023-11-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", @@ -1890,27 +2021,27 @@ "privateEndpoint_roleAssignments": { "copy": { "name": "privateEndpoint_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "privateEndpoint" ] }, "privateEndpoint_privateDnsZoneGroup": { - "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", @@ -1921,28 +2052,52 @@ "mode": "Incremental", "parameters": { "name": { - "value": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" - }, - "privateDNSResourceIds": { - "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" }, "privateEndpointName": { "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11244630631275470040" + "version": "0.29.47.4906", + "templateHash": "5805178546717255803" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", "owner": "Azure/module-maintainers" }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "privateEndpointName": { "type": "string", @@ -1950,12 +2105,15 @@ "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." } }, - "privateDNSResourceIds": { + "privateDnsZoneConfigs": { "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, "minLength": 1, "maxLength": 5, "metadata": { - "description": "Required. Array of private DNS zone resource IDs. A DNS zone group can support up to 5 DNS zones." + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." } }, "name": { @@ -1969,27 +2127,36 @@ "variables": { "copy": [ { - "name": "privateDnsZoneConfigs", - "count": "[length(parameters('privateDNSResourceIds'))]", + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", "input": { - "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", "properties": { - "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" } } } ] }, - "resources": [ - { + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", - "apiVersion": "2023-04-01", + "apiVersion": "2023-11-01", "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", "properties": { - "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" - } + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] } - ], + }, "outputs": { "name": { "type": "string", @@ -2047,14 +2214,28 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" }, "groupId": { "type": "string", "metadata": { "description": "The group Id for the private endpoint Group." }, - "value": "[if(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties.groupIds[0], reference('privateEndpoint').privateLinkServiceConnections[0].properties.groupIds[0])]" + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" } } } diff --git a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/defaults/main.test.bicep b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/defaults/main.test.bicep index 6c56f5b441..6122ab03a6 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/defaults/main.test.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/defaults/main.test.bicep @@ -50,7 +50,6 @@ module testDeployment '../../../main.bicep' = [ name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: resourceLocation administrators: [ { objectId: nestedDependencies.outputs.managedIdentityClientId @@ -60,8 +59,6 @@ module testDeployment '../../../main.bicep' = [ ] skuName: 'Standard_D2s_v3' tier: 'GeneralPurpose' - geoRedundantBackup: 'Enabled' - highAvailability: 'ZoneRedundant' } } ] diff --git a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/encr/dependencies.bicep b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/max/dependencies.bicep similarity index 100% rename from avm/res/db-for-postgre-sql/flexible-server/tests/e2e/encr/dependencies.bicep rename to avm/res/db-for-postgre-sql/flexible-server/tests/e2e/max/dependencies.bicep diff --git a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/encr/main.test.bicep b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/max/main.test.bicep similarity index 67% rename from avm/res/db-for-postgre-sql/flexible-server/tests/e2e/encr/main.test.bicep rename to avm/res/db-for-postgre-sql/flexible-server/tests/e2e/max/main.test.bicep index 1cf3100314..9013b6e853 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/encr/main.test.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/max/main.test.bicep @@ -15,7 +15,7 @@ param resourceGroupName string = 'dep-${namePrefix}-dbforpostgresql.flexibleserv param resourceLocation string = deployment().location @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'dfpsfse' +param serviceShort string = 'dfpfmax' @description('Generated. Used as a basis for unique resource names.') param baseTime string = utcNow('u') @@ -54,28 +54,28 @@ module nestedDependencies 'dependencies.bicep' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - administratorLogin: 'adminUserName' - administratorLoginPassword: password - skuName: 'Standard_D2s_v3' - tier: 'GeneralPurpose' - customerManagedKey: { - keyName: nestedDependencies.outputs.keyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId - } - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + administratorLogin: 'adminUserName' + administratorLoginPassword: password + skuName: 'Standard_D2s_v3' + tier: 'GeneralPurpose' + geoRedundantBackup: 'Disabled' + customerManagedKey: { + keyName: nestedDependencies.outputs.keyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } } } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/private/main.test.bicep b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/private/main.test.bicep index 32ac0d5321..dd3528e55b 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/private/main.test.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/private/main.test.bicep @@ -64,80 +64,81 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - administratorLogin: 'adminUserName' - administratorLoginPassword: password - skuName: 'Standard_D2s_v3' - tier: 'GeneralPurpose' - configurations: [ - { - name: 'log_min_messages' - source: 'user-override' - value: 'INFO' - } - { - name: 'autovacuum_naptime' - source: 'user-override' - value: '80' - } - ] - databases: [ - { - charset: 'UTF8' - collation: 'en_US.utf8' - name: 'testdb1' - } - { - name: 'testdb2' - } - ] - delegatedSubnetResourceId: nestedDependencies.outputs.subnetResourceId - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + administratorLogin: 'adminUserName' + administratorLoginPassword: password + skuName: 'Standard_D2s_v3' + tier: 'GeneralPurpose' + configurations: [ + { + name: 'log_min_messages' + source: 'user-override' + value: 'INFO' + } + { + name: 'autovacuum_naptime' + source: 'user-override' + value: '80' + } + ] + databases: [ + { + charset: 'UTF8' + collation: 'en_US.utf8' + name: 'testdb1' + } + { + name: 'testdb2' + } + ] + delegatedSubnetResourceId: nestedDependencies.outputs.subnetResourceId + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + geoRedundantBackup: 'Enabled' + privateDnsZoneArmResourceId: nestedDependencies.outputs.privateDNSZoneResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - geoRedundantBackup: 'Enabled' - privateDnsZoneArmResourceId: nestedDependencies.outputs.privateDNSZoneResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/public-with-pe/main.test.bicep b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/public-with-pe/main.test.bicep index f80ee12ba7..63279679eb 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/public-with-pe/main.test.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/public-with-pe/main.test.bicep @@ -71,9 +71,13 @@ module testDeployment '../../../main.bicep' = [ privateEndpoints: [ { subnetResourceId: nestedDependencies.outputs.privateEndpointSubnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: nestedDependencies.outputs.privateDNSZoneResourceId + } + ] + } tags: { 'hidden-title': 'This is visible in the resource name' Environment: 'Non-Prod' diff --git a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/public/main.test.bicep b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/public/main.test.bicep index 8d955d531f..41619743e8 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/public/main.test.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/public/main.test.bicep @@ -154,9 +154,5 @@ module testDeployment '../../../main.bicep' = [ Role: 'DeploymentValidation' } } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] } ] diff --git a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep index f33e849678..31fe160abc 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep @@ -109,7 +109,6 @@ module testDeployment '../../../main.bicep' = [ workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } ] - geoRedundantBackup: 'Enabled' privateDnsZoneArmResourceId: nestedDependencies.outputs.privateDNSZoneResourceId tags: { 'hidden-title': 'This is visible in the resource name' @@ -124,9 +123,5 @@ module testDeployment '../../../main.bicep' = [ } highAvailability: 'ZoneRedundant' } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] } ] diff --git a/avm/res/db-for-postgre-sql/flexible-server/version.json b/avm/res/db-for-postgre-sql/flexible-server/version.json index 3f863a2bec..9ed3662aba 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/version.json +++ b/avm/res/db-for-postgre-sql/flexible-server/version.json @@ -1,7 +1,7 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.6", "pathFilters": [ "./main.json" ] -} \ No newline at end of file +} diff --git a/avm/res/desktop-virtualization/host-pool/README.md b/avm/res/desktop-virtualization/host-pool/README.md index 094d7b8fad..2bc40f79dd 100644 --- a/avm/res/desktop-virtualization/host-pool/README.md +++ b/avm/res/desktop-virtualization/host-pool/README.md @@ -1006,15 +1006,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1023,6 +1021,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/desktop-virtualization/host-pool/main.bicep b/avm/res/desktop-virtualization/host-pool/main.bicep index 2084a17dd9..0f5292b6f2 100644 --- a/avm/res/desktop-virtualization/host-pool/main.bicep +++ b/avm/res/desktop-virtualization/host-pool/main.bicep @@ -447,7 +447,7 @@ type privateEndpointType = { @sys.description('Optional. Custom DNS configurations.') customDnsConfigs: { - @sys.description('Required. Fqdn that resolves to private endpoint IP address.') + @sys.description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @sys.description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/desktop-virtualization/host-pool/main.json b/avm/res/desktop-virtualization/host-pool/main.json index d11ccd0220..a15765d75b 100644 --- a/avm/res/desktop-virtualization/host-pool/main.json +++ b/avm/res/desktop-virtualization/host-pool/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "988183823258334261" + "version": "0.30.23.60470", + "templateHash": "15143229112798242850" }, "name": "Azure Virtual Desktop Host Pool", "description": "This module deploys an Azure Virtual Desktop Host Pool", @@ -284,7 +284,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { diff --git a/avm/res/desktop-virtualization/workspace/README.md b/avm/res/desktop-virtualization/workspace/README.md index bc71f372f4..48551acfb4 100644 --- a/avm/res/desktop-virtualization/workspace/README.md +++ b/avm/res/desktop-virtualization/workspace/README.md @@ -924,15 +924,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -941,6 +939,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/desktop-virtualization/workspace/main.bicep b/avm/res/desktop-virtualization/workspace/main.bicep index b491177c31..b333a5316c 100644 --- a/avm/res/desktop-virtualization/workspace/main.bicep +++ b/avm/res/desktop-virtualization/workspace/main.bicep @@ -330,7 +330,7 @@ type privateEndpointType = { @sys.description('Optional. Custom DNS configurations.') customDnsConfigs: { - @sys.description('Required. Fqdn that resolves to private endpoint IP address.') + @sys.description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @sys.description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/desktop-virtualization/workspace/main.json b/avm/res/desktop-virtualization/workspace/main.json index de5bdd06a4..8245d8ae67 100644 --- a/avm/res/desktop-virtualization/workspace/main.json +++ b/avm/res/desktop-virtualization/workspace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8425031488997615382" + "version": "0.30.23.60470", + "templateHash": "4950797341752129951" }, "name": "Workspace", "description": "This module deploys an Azure Virtual Desktop Workspace.", @@ -277,7 +277,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { diff --git a/avm/res/dev-ops-infrastructure/pool/README.md b/avm/res/dev-ops-infrastructure/pool/README.md index 9896670d02..9b7d40e881 100644 --- a/avm/res/dev-ops-infrastructure/pool/README.md +++ b/avm/res/dev-ops-infrastructure/pool/README.md @@ -17,7 +17,7 @@ This module deploys the Managed DevOps Pool resource. | :-- | :-- | | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | -| `Microsoft.DevOpsInfrastructure/pools` | [2024-04-04-preview](https://learn.microsoft.com/en-us/azure/templates) | +| `Microsoft.DevOpsInfrastructure/pools` | [2024-10-19](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DevOpsInfrastructure/2024-10-19/pools) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | ## Usage examples @@ -182,26 +182,24 @@ module pool 'br/public:avm/res/dev-ops-infrastructure/pool:' = { agentProfile: { kind: 'Stateless' resourcePredictions: { - daysData: [ - { - '09:00:00': 1 - '17:00:00': 0 + daysData: { + friday: { + endAgentCount: 0 + endTime: '17:00:00' + startAgentCount: 1 + startTime: '09:00:00' } - {} - {} - {} - { - '09:00:00': 1 - '17:00:00': 0 + monday: { + endAgentCount: 0 + endTime: '17:00:00' + startAgentCount: 1 + startTime: '09:00:00' } - {} - {} - ] - timeZone: 'Central Europe Standard Time' + } + timeZone: 'UTC' } resourcePredictionsProfile: { - kind: 'Automatic' - predictionPreference: 'Balanced' + kind: 'Manual' } } concurrency: 1 @@ -293,26 +291,24 @@ module pool 'br/public:avm/res/dev-ops-infrastructure/pool:' = { "value": { "kind": "Stateless", "resourcePredictions": { - "daysData": [ - { - "09:00:00": 1, - "17:00:00": 0 - }, - {}, - {}, - {}, - { - "09:00:00": 1, - "17:00:00": 0 + "daysData": { + "friday": { + "endAgentCount": 0, + "endTime": "17:00:00", + "startAgentCount": 1, + "startTime": "09:00:00" }, - {}, - {} - ], - "timeZone": "Central Europe Standard Time" + "monday": { + "endAgentCount": 0, + "endTime": "17:00:00", + "startAgentCount": 1, + "startTime": "09:00:00" + } + }, + "timeZone": "UTC" }, "resourcePredictionsProfile": { - "kind": "Automatic", - "predictionPreference": "Balanced" + "kind": "Manual" } } }, @@ -426,26 +422,24 @@ using 'br/public:avm/res/dev-ops-infrastructure/pool:' param agentProfile = { kind: 'Stateless' resourcePredictions: { - daysData: [ - { - '09:00:00': 1 - '17:00:00': 0 + daysData: { + friday: { + endAgentCount: 0 + endTime: '17:00:00' + startAgentCount: 1 + startTime: '09:00:00' } - {} - {} - {} - { - '09:00:00': 1 - '17:00:00': 0 + monday: { + endAgentCount: 0 + endTime: '17:00:00' + startAgentCount: 1 + startTime: '09:00:00' } - {} - {} - ] - timeZone: 'Central Europe Standard Time' + } + timeZone: 'UTC' } resourcePredictionsProfile: { - kind: 'Automatic' - predictionPreference: 'Balanced' + kind: 'Manual' } } param concurrency = 1 @@ -537,24 +531,6 @@ module pool 'br/public:avm/res/dev-ops-infrastructure/pool:' = { // Required parameters agentProfile: { kind: 'Stateless' - resourcePredictions: { - daysData: [ - { - '09:00:00': 1 - '17:00:00': 0 - } - {} - {} - {} - { - '09:00:00': 1 - '17:00:00': 0 - } - {} - {} - ] - timeZone: 'Central Europe Standard Time' - } resourcePredictionsProfile: { kind: 'Automatic' predictionPreference: 'Balanced' @@ -607,24 +583,6 @@ module pool 'br/public:avm/res/dev-ops-infrastructure/pool:' = { "agentProfile": { "value": { "kind": "Stateless", - "resourcePredictions": { - "daysData": [ - { - "09:00:00": 1, - "17:00:00": 0 - }, - {}, - {}, - {}, - { - "09:00:00": 1, - "17:00:00": 0 - }, - {}, - {} - ], - "timeZone": "Central Europe Standard Time" - }, "resourcePredictionsProfile": { "kind": "Automatic", "predictionPreference": "Balanced" @@ -691,24 +649,6 @@ using 'br/public:avm/res/dev-ops-infrastructure/pool:' // Required parameters param agentProfile = { kind: 'Stateless' - resourcePredictions: { - daysData: [ - { - '09:00:00': 1 - '17:00:00': 0 - } - {} - {} - {} - { - '09:00:00': 1 - '17:00:00': 0 - } - {} - {} - ] - timeZone: 'Central Europe Standard Time' - } resourcePredictionsProfile: { kind: 'Automatic' predictionPreference: 'Balanced' diff --git a/avm/res/dev-ops-infrastructure/pool/main.bicep b/avm/res/dev-ops-infrastructure/pool/main.bicep index 358dd0abf5..8dbaad49b5 100644 --- a/avm/res/dev-ops-infrastructure/pool/main.bicep +++ b/avm/res/dev-ops-infrastructure/pool/main.bicep @@ -114,6 +114,19 @@ var identity = !empty(managedIdentities) } : null +var formattedDaysData = !empty(agentProfile.?resourcePredictions.?daysData) + ? map( + ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + day => + contains(agentProfile.resourcePredictions.daysData, day) + ? { + '${agentProfile.resourcePredictions.daysData[day].startTime}': agentProfile.resourcePredictions.daysData[day].startAgentCount + '${agentProfile.resourcePredictions.daysData[day].endTime}': agentProfile.resourcePredictions.daysData[day].endAgentCount + } + : {} + ) + : null + #disable-next-line no-deployments-resources resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { name: '46d3xbcp.res.devopsinfrastructure-pool.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' @@ -133,13 +146,36 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableT } } -resource managedDevOpsPool 'Microsoft.DevOpsInfrastructure/pools@2024-04-04-preview' = { +resource managedDevOpsPool 'Microsoft.DevOpsInfrastructure/pools@2024-10-19' = { name: name location: location tags: tags identity: identity properties: { - agentProfile: agentProfile + // agentProfile: agentProfile + agentProfile: agentProfile.kind == 'Stateful' + ? { + kind: 'Stateful' + maxAgentLifetime: agentProfile.maxAgentLifetime + gracePeriodTimeSpan: agentProfile.gracePeriodTimeSpan + resourcePredictions: !empty(agentProfile.?resourcePredictions) + ? { + timeZone: agentProfile.?resourcePredictions.timeZone + daysData: formattedDaysData + } + : null + resourcePredictionsProfile: agentProfile.?resourcePredictionsProfile + } + : { + kind: 'Stateless' + resourcePredictions: !empty(agentProfile.?resourcePredictions) + ? { + timeZone: agentProfile.?resourcePredictions.timeZone + daysData: formattedDaysData + } + : null + resourcePredictionsProfile: agentProfile.?resourcePredictionsProfile + } devCenterProjectResourceId: devCenterProjectResourceId fabricProfile: { sku: { @@ -363,7 +399,13 @@ type agentStatefulType = { gracePeriodTimeSpan: string @description('Optional. Defines pool buffer/stand-by agents.') - resourcePredictions: object? + resourcePredictions: { + @description('Required. The time zone in which the daysData is provided. To see the list of available time zones, see: https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones?view=windows-11#time-zones or via PowerShell command `(Get-TimeZone -ListAvailable).StandardName`.') + timeZone: string + + @description('Optional. The number of agents needed at a specific time.') + daysData: daysDataType + }? @discriminator('kind') @description('Optional. Determines how the stand-by scheme should be provided.') @@ -381,26 +423,7 @@ type agentStatelessType = { timeZone: string @description('Optional. The number of agents needed at a specific time.') - @metadata({ - example: ''' - [ - { // Monday - '09:00': 5 - '22:00': 0 - } - {} // Tuesday - {} // Wednesday - {} // Thursday - { // Friday - '09:00': 5 - '22:00': 0 - } - {} // Saturday - {} // Sunday - ] - ''' - }) - daysData: object[]? + daysData: daysDataType }? @discriminator('kind') @@ -501,3 +524,42 @@ type managedIdentitiesType = { @description('Optional. The resource ID(s) to assign to the resource.') userAssignedResourceIds: string[]? }? + +@export() +type standbyAgentsConfigType = { + @description('Required. The time at which the agents are needed.') + startTime: string + + @description('Required. The time at which the agents are no longer needed.') + endTime: string + + @description('Required. The number of agents needed at the start time.') + startAgentCount: int + + @description('Required. The number of agents needed at the end time.') + endAgentCount: int +}? + +@export() +type daysDataType = { + @description('Optional. The number of agents needed at a specific time for Monday.') + monday: standbyAgentsConfigType + + @description('Optional. The number of agents needed at a specific time for Tuesday.') + tuesday: standbyAgentsConfigType + + @description('Optional. The number of agents needed at a specific time for Wednesday.') + wednesday: standbyAgentsConfigType + + @description('Optional. The number of agents needed at a specific time for Thursday.') + thursday: standbyAgentsConfigType + + @description('Optional. The number of agents needed at a specific time for Friday.') + friday: standbyAgentsConfigType + + @description('Optional. The number of agents needed at a specific time for Saturday.') + saturday: standbyAgentsConfigType + + @description('Optional. The number of agents needed at a specific time for Sunday.') + sunday: standbyAgentsConfigType +}? diff --git a/avm/res/dev-ops-infrastructure/pool/main.json b/avm/res/dev-ops-infrastructure/pool/main.json index 05c3db9232..9607831b9e 100644 --- a/avm/res/dev-ops-infrastructure/pool/main.json +++ b/avm/res/dev-ops-infrastructure/pool/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14560645908978883645" + "version": "0.31.34.60546", + "templateHash": "14164073542984791131" }, "name": "Managed DevOps Pool", "description": "This module deploys the Managed DevOps Pool resource.", @@ -392,6 +392,20 @@ }, "resourcePredictions": { "type": "object", + "properties": { + "timeZone": { + "type": "string", + "metadata": { + "description": "Required. The time zone in which the daysData is provided. To see the list of available time zones, see: https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones?view=windows-11#time-zones or via PowerShell command `(Get-TimeZone -ListAvailable).StandardName`." + } + }, + "daysData": { + "$ref": "#/definitions/daysDataType", + "metadata": { + "description": "Optional. The number of agents needed at a specific time." + } + } + }, "nullable": true, "metadata": { "description": "Optional. Defines pool buffer/stand-by agents." @@ -442,13 +456,8 @@ } }, "daysData": { - "type": "array", - "items": { - "type": "object" - }, - "nullable": true, + "$ref": "#/definitions/daysDataType", "metadata": { - "example": " [\n { // Monday\n '09:00': 5\n '22:00': 0\n }\n {} // Tuesday\n {} // Wednesday\n {} // Thursday\n { // Friday\n '09:00': 5\n '22:00': 0\n }\n {} // Saturday\n {} // Sunday\n ]\n ", "description": "Optional. The number of agents needed at a specific time." } } @@ -750,6 +759,90 @@ "metadata": { "__bicep_export!": true } + }, + "standbyAgentsConfigType": { + "type": "object", + "properties": { + "startTime": { + "type": "string", + "metadata": { + "description": "Required. The time at which the agents are needed." + } + }, + "endTime": { + "type": "string", + "metadata": { + "description": "Required. The time at which the agents are no longer needed." + } + }, + "startAgentCount": { + "type": "int", + "metadata": { + "description": "Required. The number of agents needed at the start time." + } + }, + "endAgentCount": { + "type": "int", + "metadata": { + "description": "Required. The number of agents needed at the end time." + } + } + }, + "nullable": true, + "metadata": { + "__bicep_export!": true + } + }, + "daysDataType": { + "type": "object", + "properties": { + "monday": { + "$ref": "#/definitions/standbyAgentsConfigType", + "metadata": { + "description": "Optional. The number of agents needed at a specific time for Monday." + } + }, + "tuesday": { + "$ref": "#/definitions/standbyAgentsConfigType", + "metadata": { + "description": "Optional. The number of agents needed at a specific time for Tuesday." + } + }, + "wednesday": { + "$ref": "#/definitions/standbyAgentsConfigType", + "metadata": { + "description": "Optional. The number of agents needed at a specific time for Wednesday." + } + }, + "thursday": { + "$ref": "#/definitions/standbyAgentsConfigType", + "metadata": { + "description": "Optional. The number of agents needed at a specific time for Thursday." + } + }, + "friday": { + "$ref": "#/definitions/standbyAgentsConfigType", + "metadata": { + "description": "Optional. The number of agents needed at a specific time for Friday." + } + }, + "saturday": { + "$ref": "#/definitions/standbyAgentsConfigType", + "metadata": { + "description": "Optional. The number of agents needed at a specific time for Saturday." + } + }, + "sunday": { + "$ref": "#/definitions/standbyAgentsConfigType", + "metadata": { + "description": "Optional. The number of agents needed at a specific time for Sunday." + } + } + }, + "nullable": true, + "metadata": { + "__bicep_export!": true + } } }, "parameters": { @@ -889,7 +982,8 @@ "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" }, "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", - "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', 'None')), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]" + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', 'None')), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "formattedDaysData": "[if(not(empty(tryGet(tryGet(parameters('agentProfile'), 'resourcePredictions'), 'daysData'))), map(createArray('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'), lambda('day', if(contains(parameters('agentProfile').resourcePredictions.daysData, lambdaVariables('day')), createObject(format('{0}', parameters('agentProfile').resourcePredictions.daysData[lambdaVariables('day')].startTime), parameters('agentProfile').resourcePredictions.daysData[lambdaVariables('day')].startAgentCount, format('{0}', parameters('agentProfile').resourcePredictions.daysData[lambdaVariables('day')].endTime), parameters('agentProfile').resourcePredictions.daysData[lambdaVariables('day')].endAgentCount), createObject()))), null())]" }, "resources": { "avmTelemetry": { @@ -914,13 +1008,13 @@ }, "managedDevOpsPool": { "type": "Microsoft.DevOpsInfrastructure/pools", - "apiVersion": "2024-04-04-preview", + "apiVersion": "2024-10-19", "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", "identity": "[variables('identity')]", "properties": { - "agentProfile": "[parameters('agentProfile')]", + "agentProfile": "[if(equals(parameters('agentProfile').kind, 'Stateful'), createObject('kind', 'Stateful', 'maxAgentLifetime', parameters('agentProfile').maxAgentLifetime, 'gracePeriodTimeSpan', parameters('agentProfile').gracePeriodTimeSpan, 'resourcePredictions', if(not(empty(tryGet(parameters('agentProfile'), 'resourcePredictions'))), createObject('timeZone', tryGet(parameters('agentProfile'), 'resourcePredictions', 'timeZone'), 'daysData', variables('formattedDaysData')), null()), 'resourcePredictionsProfile', tryGet(parameters('agentProfile'), 'resourcePredictionsProfile')), createObject('kind', 'Stateless', 'resourcePredictions', if(not(empty(tryGet(parameters('agentProfile'), 'resourcePredictions'))), createObject('timeZone', tryGet(parameters('agentProfile'), 'resourcePredictions', 'timeZone'), 'daysData', variables('formattedDaysData')), null()), 'resourcePredictionsProfile', tryGet(parameters('agentProfile'), 'resourcePredictionsProfile')))]", "devCenterProjectResourceId": "[parameters('devCenterProjectResourceId')]", "fabricProfile": { "sku": { @@ -1041,7 +1135,7 @@ "metadata": { "description": "The location the Managed DevOps Pool resource was deployed into." }, - "value": "[reference('managedDevOpsPool', '2024-04-04-preview', 'full').location]" + "value": "[reference('managedDevOpsPool', '2024-10-19', 'full').location]" }, "systemAssignedMIPrincipalId": { "type": "string", @@ -1049,7 +1143,7 @@ "metadata": { "description": "The principal ID of the system assigned identity." }, - "value": "[tryGet(tryGet(reference('managedDevOpsPool', '2024-04-04-preview', 'full'), 'identity'), 'principalId')]" + "value": "[tryGet(tryGet(reference('managedDevOpsPool', '2024-10-19', 'full'), 'identity'), 'principalId')]" } } } \ No newline at end of file diff --git a/avm/res/dev-ops-infrastructure/pool/tests/e2e/max/main.test.bicep b/avm/res/dev-ops-infrastructure/pool/tests/e2e/max/main.test.bicep index 09b40200e5..5a5ce51cb2 100644 --- a/avm/res/dev-ops-infrastructure/pool/tests/e2e/max/main.test.bicep +++ b/avm/res/dev-ops-infrastructure/pool/tests/e2e/max/main.test.bicep @@ -70,33 +70,24 @@ module testDeployment '../../../main.bicep' = [ agentProfile: { kind: 'Stateless' resourcePredictions: { - timeZone: 'Central Europe Standard Time' - daysData: [ - // Monday - { - '09:00:00': 1 - '17:00:00': 0 + timeZone: 'UTC' + daysData: { + monday: { + startTime: '09:00:00' + startAgentCount: 1 + endTime: '17:00:00' + endAgentCount: 0 } - // Tuesday - {} - // Wednesday - {} - // Thursday - {} - // Friday - { - '09:00:00': 1 - '17:00:00': 0 + friday: { + startTime: '09:00:00' + startAgentCount: 1 + endTime: '17:00:00' + endAgentCount: 0 } - // Saturday - {} - // Sunday - {} - ] + } } resourcePredictionsProfile: { - kind: 'Automatic' - predictionPreference: 'Balanced' + kind: 'Manual' } } concurrency: 1 diff --git a/avm/res/dev-ops-infrastructure/pool/tests/e2e/waf-aligned/main.test.bicep b/avm/res/dev-ops-infrastructure/pool/tests/e2e/waf-aligned/main.test.bicep index 20a04a3900..884f636192 100644 --- a/avm/res/dev-ops-infrastructure/pool/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/dev-ops-infrastructure/pool/tests/e2e/waf-aligned/main.test.bicep @@ -69,31 +69,6 @@ module testDeployment '../../../main.bicep' = [ location: enforcedLocation agentProfile: { kind: 'Stateless' - resourcePredictions: { - timeZone: 'Central Europe Standard Time' - daysData: [ - // Monday - { - '09:00:00': 1 - '17:00:00': 0 - } - // Tuesday - {} - // Wednesday - {} - // Thursday - {} - // Friday - { - '09:00:00': 1 - '17:00:00': 0 - } - // Saturday - {} - // Sunday - {} - ] - } resourcePredictionsProfile: { kind: 'Automatic' predictionPreference: 'Balanced' diff --git a/avm/res/dev-ops-infrastructure/pool/version.json b/avm/res/dev-ops-infrastructure/pool/version.json index 8def869ede..729ac87673 100644 --- a/avm/res/dev-ops-infrastructure/pool/version.json +++ b/avm/res/dev-ops-infrastructure/pool/version.json @@ -1,7 +1,7 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.2", "pathFilters": [ "./main.json" ] -} +} \ No newline at end of file diff --git a/avm/res/digital-twins/digital-twins-instance/README.md b/avm/res/digital-twins/digital-twins-instance/README.md index 1cb5feb1f6..ac4beeb9a4 100644 --- a/avm/res/digital-twins/digital-twins-instance/README.md +++ b/avm/res/digital-twins/digital-twins-instance/README.md @@ -988,15 +988,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1005,6 +1003,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/digital-twins/digital-twins-instance/main.bicep b/avm/res/digital-twins/digital-twins-instance/main.bicep index a05e44eb8a..6ebafb65f6 100644 --- a/avm/res/digital-twins/digital-twins-instance/main.bicep +++ b/avm/res/digital-twins/digital-twins-instance/main.bicep @@ -385,7 +385,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/digital-twins/digital-twins-instance/main.json b/avm/res/digital-twins/digital-twins-instance/main.json index ea549b4b6a..ee05f0f0bd 100644 --- a/avm/res/digital-twins/digital-twins-instance/main.json +++ b/avm/res/digital-twins/digital-twins-instance/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "6681425649721370761" + "version": "0.30.23.60470", + "templateHash": "11503001274179673847" }, "name": "Digital Twins Instances", "description": "This module deploys an Azure Digital Twins Instance.", @@ -207,7 +207,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -695,8 +695,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "13720195975702696848" + "version": "0.30.23.60470", + "templateHash": "16914787878954195877" }, "name": "Digital Twins Instance EventHub Endpoint", "description": "This module deploys a Digital Twins Instance EventHub Endpoint.", @@ -893,8 +893,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "17105935055209854005" + "version": "0.30.23.60470", + "templateHash": "17261842587165157796" }, "name": "Digital Twins Instance Event Grid Endpoints", "description": "This module deploys a Digital Twins Instance Event Grid Endpoint.", @@ -1020,8 +1020,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "13764805272277592098" + "version": "0.30.23.60470", + "templateHash": "843606537345038481" }, "name": "Digital Twins Instance ServiceBus Endpoint", "description": "This module deploys a Digital Twins Instance ServiceBus Endpoint.", diff --git a/avm/res/document-db/database-account/README.md b/avm/res/document-db/database-account/README.md index 44848ebee3..b7b6f578cf 100644 --- a/avm/res/document-db/database-account/README.md +++ b/avm/res/document-db/database-account/README.md @@ -26,6 +26,7 @@ This module deploys a DocumentDB Database Account. | `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers` | [2023-04-15](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2023-04-15/databaseAccounts/sqlDatabases/containers) | | `Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments` | [2023-04-15](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2023-04-15/databaseAccounts/sqlRoleAssignments) | | `Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions` | [2023-04-15](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2023-04-15/databaseAccounts/sqlRoleDefinitions) | +| `Microsoft.DocumentDB/databaseAccounts/tables` | [2023-04-15](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2023-04-15/databaseAccounts/tables) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | | `Microsoft.KeyVault/vaults/secrets` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2023-07-01/vaults/secrets) | | `Microsoft.Network/privateEndpoints` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints) | @@ -51,7 +52,8 @@ The following section provides usage examples for the module, which were used to - [Public network restricted access with ACL](#example-10-public-network-restricted-access-with-acl) - [Deploying with a sql role definision and assignment](#example-11-deploying-with-a-sql-role-definision-and-assignment) - [SQL Database](#example-12-sql-database) -- [WAF-aligned](#example-13-waf-aligned) +- [API for Table](#example-13-api-for-table) +- [WAF-aligned](#example-14-waf-aligned) ### Example 1: _Using analytical storage_ @@ -3054,7 +3056,114 @@ param sqlDatabases = [

    -### Example 13: _WAF-aligned_ +### Example 13: _API for Table_ + +This instance deploys the module for an Azure Cosmos DB for Table account with two example tables. + + +

    + +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: 'databaseAccountDeployment' + params: { + // Required parameters + name: 'dddatbl001' + // Non-required parameters + capabilitiesToAdd: [ + 'EnableTable' + ] + location: '' + tables: [ + { + name: 'tbl-dddatableminprov' + throughput: 400 + } + { + maxThroughput: 1000 + name: 'tbl-dddatableminauto' + } + ] + } +} +``` + +
    +

    + +

    + +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dddatbl001" + }, + // Non-required parameters + "capabilitiesToAdd": { + "value": [ + "EnableTable" + ] + }, + "location": { + "value": "" + }, + "tables": { + "value": [ + { + "name": "tbl-dddatableminprov", + "throughput": 400 + }, + { + "maxThroughput": 1000, + "name": "tbl-dddatableminauto" + } + ] + } + } +} +``` + +
    +

    + +

    + +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/document-db/database-account:' + +// Required parameters +param name = 'dddatbl001' +// Non-required parameters +param capabilitiesToAdd = [ + 'EnableTable' +] +param location = '' +param tables = [ + { + name: 'tbl-dddatableminprov' + throughput: 400 + } + { + maxThroughput: 1000 + name: 'tbl-dddatableminauto' + } +] +``` + +
    +

    + +### Example 14: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. @@ -3299,7 +3408,7 @@ param tags = { | [`backupRetentionIntervalInHours`](#parameter-backupretentionintervalinhours) | int | Default to 8. An integer representing the time (in hours) that each backup is retained. Only applies to periodic backup type. | | [`backupStorageRedundancy`](#parameter-backupstorageredundancy) | string | Default to Local. Enum to indicate type of backup residency. Only applies to periodic backup type. | | [`capabilitiesToAdd`](#parameter-capabilitiestoadd) | array | List of Cosmos DB capabilities for the account. | -| [`databaseAccountOfferType`](#parameter-databaseaccountoffertype) | string | Default to Standard. The offer type for the Cosmos DB database account. | +| [`databaseAccountOfferType`](#parameter-databaseaccountoffertype) | string | Default to Standard. The offer type for the Azure Cosmos DB database account. | | [`defaultConsistencyLevel`](#parameter-defaultconsistencylevel) | string | Default to Session. The default consistency level of the Cosmos DB account. | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | | [`disableKeyBasedMetadataWriteAccess`](#parameter-disablekeybasedmetadatawriteaccess) | bool | Disable write operations on metadata resources (databases, containers, throughput) via account keys. | @@ -3315,8 +3424,9 @@ param tags = { | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | | [`maxIntervalInSeconds`](#parameter-maxintervalinseconds) | int | Default to 300. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400. | | [`maxStalenessPrefix`](#parameter-maxstalenessprefix) | int | Default to 100000. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000. | +| [`minimumTlsVersion`](#parameter-minimumtlsversion) | string | Default to TLS 1.2. Enum to indicate the minimum allowed TLS version. Azure Cosmos DB for MongoDB RU and Apache Cassandra only work with TLS 1.2 or later. | | [`mongodbDatabases`](#parameter-mongodbdatabases) | array | MongoDB Databases configurations. | -| [`networkRestrictions`](#parameter-networkrestrictions) | object | The network configuration of this module. | +| [`networkRestrictions`](#parameter-networkrestrictions) | object | The network configuration of this module. Defaults to `{ ipRules: [], virtualNetworkRules: [], publicNetworkAccess: 'Disabled' }`. | | [`privateEndpoints`](#parameter-privateendpoints) | array | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | | [`roleAssignments`](#parameter-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'. | | [`secretsExportConfiguration`](#parameter-secretsexportconfiguration) | object | Key vault reference and secret settings for the module's secrets export. | @@ -3324,6 +3434,7 @@ param tags = { | [`sqlDatabases`](#parameter-sqldatabases) | array | SQL Databases configurations. | | [`sqlRoleAssignmentsPrincipalIds`](#parameter-sqlroleassignmentsprincipalids) | array | SQL Role Definitions configurations. | | [`sqlRoleDefinitions`](#parameter-sqlroledefinitions) | array | SQL Role Definitions configurations. | +| [`tables`](#parameter-tables) | array | Table configurations. | | [`tags`](#parameter-tags) | object | Tags of the Database Account resource. | ### Parameter: `name` @@ -3424,7 +3535,7 @@ List of Cosmos DB capabilities for the account. ### Parameter: `databaseAccountOfferType` -Default to Standard. The offer type for the Cosmos DB database account. +Default to Standard. The offer type for the Azure Cosmos DB database account. - Required: No - Type: string @@ -3606,7 +3717,7 @@ Disable write operations on metadata resources (databases, containers, throughpu - Required: No - Type: bool -- Default: `False` +- Default: `True` ### Parameter: `disableLocalAuth` @@ -3786,6 +3897,22 @@ Default to 100000. Max stale requests. Required for BoundedStaleness. Valid rang - Type: int - Default: `100000` +### Parameter: `minimumTlsVersion` + +Default to TLS 1.2. Enum to indicate the minimum allowed TLS version. Azure Cosmos DB for MongoDB RU and Apache Cassandra only work with TLS 1.2 or later. + +- Required: No +- Type: string +- Default: `'Tls12'` +- Allowed: + ```Bicep + [ + 'Tls' + 'Tls11' + 'Tls12' + ] + ``` + ### Parameter: `mongodbDatabases` MongoDB Databases configurations. @@ -3796,27 +3923,60 @@ MongoDB Databases configurations. ### Parameter: `networkRestrictions` -The network configuration of this module. +The network configuration of this module. Defaults to `{ ipRules: [], virtualNetworkRules: [], publicNetworkAccess: 'Disabled' }`. - Required: No - Type: object +- Default: + ```Bicep + { + ipRules: [] + publicNetworkAccess: 'Disabled' + virtualNetworkRules: [] + } + ``` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`ipRules`](#parameter-networkrestrictionsiprules) | array | A single IPv4 address or a single IPv4 address range in CIDR format. Provided IPs must be well-formatted and cannot be contained in one of the following ranges: 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, since these are not enforceable by the IP address filter. Example of valid inputs: "23.40.210.245" or "23.40.210.0/8". | +| [`virtualNetworkRules`](#parameter-networkrestrictionsvirtualnetworkrules) | array | List of Virtual Network ACL rules configured for the Cosmos DB account.. | **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | -| [`ipRules`](#parameter-networkrestrictionsiprules) | array | Default to []. A single IPv4 address or a single IPv4 address range in CIDR format. Provided IPs must be well-formatted and cannot be contained in one of the following ranges: 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, since these are not enforceable by the IP address filter. Example of valid inputs: "23.40.210.245" or "23.40.210.0/8". | | [`networkAclBypass`](#parameter-networkrestrictionsnetworkaclbypass) | string | Default to AzureServices. Specifies the network ACL bypass for Azure services. | | [`publicNetworkAccess`](#parameter-networkrestrictionspublicnetworkaccess) | string | Default to Enabled. Whether requests from Public Network are allowed. | -| [`virtualNetworkRules`](#parameter-networkrestrictionsvirtualnetworkrules) | array | Default to []. List of Virtual Network ACL rules configured for the Cosmos DB account.. | ### Parameter: `networkRestrictions.ipRules` -Default to []. A single IPv4 address or a single IPv4 address range in CIDR format. Provided IPs must be well-formatted and cannot be contained in one of the following ranges: 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, since these are not enforceable by the IP address filter. Example of valid inputs: "23.40.210.245" or "23.40.210.0/8". +A single IPv4 address or a single IPv4 address range in CIDR format. Provided IPs must be well-formatted and cannot be contained in one of the following ranges: 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, since these are not enforceable by the IP address filter. Example of valid inputs: "23.40.210.245" or "23.40.210.0/8". + +- Required: Yes +- Type: array + +### Parameter: `networkRestrictions.virtualNetworkRules` + +List of Virtual Network ACL rules configured for the Cosmos DB account.. - Required: Yes - Type: array +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetResourceId`](#parameter-networkrestrictionsvirtualnetworkrulessubnetresourceid) | string | Resource ID of a subnet. | + +### Parameter: `networkRestrictions.virtualNetworkRules.subnetResourceId` + +Resource ID of a subnet. + +- Required: Yes +- Type: string + ### Parameter: `networkRestrictions.networkAclBypass` Default to AzureServices. Specifies the network ACL bypass for Azure services. @@ -3845,26 +4005,6 @@ Default to Enabled. Whether requests from Public Network are allowed. ] ``` -### Parameter: `networkRestrictions.virtualNetworkRules` - -Default to []. List of Virtual Network ACL rules configured for the Cosmos DB account.. - -- Required: Yes -- Type: array - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`subnetResourceId`](#parameter-networkrestrictionsvirtualnetworkrulessubnetresourceid) | string | Resource ID of a subnet. | - -### Parameter: `networkRestrictions.virtualNetworkRules.subnetResourceId` - -Resource ID of a subnet. - -- Required: Yes -- Type: string - ### Parameter: `privateEndpoints` Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. @@ -3931,15 +4071,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint ip address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private ip addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint ip address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -3948,6 +4086,13 @@ A list of private ip addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -4765,6 +4910,14 @@ Indicates whether the Role Definition was built-in or user created. ] ``` +### Parameter: `tables` + +Table configurations. + +- Required: No +- Type: array +- Default: `[]` + ### Parameter: `tags` Tags of the Database Account resource. diff --git a/avm/res/document-db/database-account/gremlin-database/graph/main.json b/avm/res/document-db/database-account/gremlin-database/graph/main.json index 13655f07f3..96761953b4 100644 --- a/avm/res/document-db/database-account/gremlin-database/graph/main.json +++ b/avm/res/document-db/database-account/gremlin-database/graph/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9917502444704809829" + "version": "0.30.23.60470", + "templateHash": "5396990720772518636" }, "name": "DocumentDB Database Accounts Gremlin Databases Graphs", "description": "This module deploys a DocumentDB Database Accounts Gremlin Database Graph.", diff --git a/avm/res/document-db/database-account/gremlin-database/main.json b/avm/res/document-db/database-account/gremlin-database/main.json index 4f38214e0d..5dcde760ef 100644 --- a/avm/res/document-db/database-account/gremlin-database/main.json +++ b/avm/res/document-db/database-account/gremlin-database/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7926803681315745584" + "version": "0.30.23.60470", + "templateHash": "14612267479855031826" }, "name": "DocumentDB Database Account Gremlin Databases", "description": "This module deploys a Gremlin Database within a CosmosDB Account.", @@ -111,8 +111,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9917502444704809829" + "version": "0.30.23.60470", + "templateHash": "5396990720772518636" }, "name": "DocumentDB Database Accounts Gremlin Databases Graphs", "description": "This module deploys a DocumentDB Database Accounts Gremlin Database Graph.", diff --git a/avm/res/document-db/database-account/main.bicep b/avm/res/document-db/database-account/main.bicep index bde70c52ef..d5a168c79b 100644 --- a/avm/res/document-db/database-account/main.bicep +++ b/avm/res/document-db/database-account/main.bicep @@ -14,7 +14,7 @@ param tags object? @description('Optional. The managed identity definition for this resource.') param managedIdentities managedIdentitiesType -@description('Optional. Default to Standard. The offer type for the Cosmos DB database account.') +@description('Optional. Default to Standard. The offer type for the Azure Cosmos DB database account.') @allowed([ 'Standard' ]) @@ -49,7 +49,7 @@ param enableFreeTier bool = false param enableMultipleWriteLocations bool = false @description('Optional. Disable write operations on metadata resources (databases, containers, throughput) via account keys.') -param disableKeyBasedMetadataWriteAccess bool = false +param disableKeyBasedMetadataWriteAccess bool = true @minValue(1) @maxValue(2147483647) @@ -85,6 +85,9 @@ param mongodbDatabases array = [] @description('Optional. Gremlin Databases configurations.') param gremlinDatabases array = [] +@description('Optional. Table configurations.') +param tables array = [] + @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true @@ -146,8 +149,20 @@ param privateEndpoints privateEndpointType @description('Optional. Key vault reference and secret settings for the module\'s secrets export.') param secretsExportConfiguration secretsExportConfigurationType? -@description('Optional. The network configuration of this module.') -param networkRestrictions networkRestrictionsType? +@description('Optional. The network configuration of this module. Defaults to `{ ipRules: [], virtualNetworkRules: [], publicNetworkAccess: \'Disabled\' }`.') +param networkRestrictions networkRestrictionsType = { + ipRules: [] + virtualNetworkRules: [] + publicNetworkAccess: 'Disabled' +} + +@allowed([ + 'Tls' + 'Tls11' + 'Tls12' +]) +@description('Optional. Default to TLS 1.2. Enum to indicate the minimum allowed TLS version. Azure Cosmos DB for MongoDB RU and Apache Cassandra only work with TLS 1.2 or later.') +param minimumTlsVersion string = 'Tls12' var formattedUserAssignedIdentities = reduce( map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), @@ -243,10 +258,11 @@ var databaseAccountProperties = union( { databaseAccountOfferType: databaseAccountOfferType backupPolicy: backupPolicy + minimalTlsVersion: minimumTlsVersion }, - ((!empty(sqlDatabases) || !empty(mongodbDatabases) || !empty(gremlinDatabases)) + ((!empty(sqlDatabases) || !empty(mongodbDatabases) || !empty(gremlinDatabases) || !empty(tables)) ? { - // Common properties + // NoSQL, MongoDB RU, Table, and Apache Gremlin common properties consistencyPolicy: consistencyPolicy[defaultConsistencyLevel] enableMultipleWriteLocations: enableMultipleWriteLocations locations: empty(databaseAccount_locations) ? defaultFailoverLocation : databaseAccount_locations @@ -263,16 +279,16 @@ var databaseAccountProperties = union( enableAnalyticalStorage: enableAnalyticalStorage } : {}), - (!empty(sqlDatabases) + ((!empty(sqlDatabases) || !empty(tables)) ? { - // SQLDB properties + // NoSQL and Table properties disableLocalAuth: disableLocalAuth disableKeyBasedMetadataWriteAccess: disableKeyBasedMetadataWriteAccess } : {}), (!empty(mongodbDatabases) ? { - // MongoDb properties + // MongoDB RU properties apiProperties: { serverVersion: serverVersion } @@ -463,6 +479,19 @@ module databaseAccount_gremlinDatabases 'gremlin-database/main.bicep' = [ } ] +module databaseAccount_tables 'table/main.bicep' = [ + for table in tables: { + name: '${uniqueString(deployment().name, location)}-table-${table.name}' + params: { + databaseAccountName: databaseAccount.name + name: table.name + tags: table.?tags ?? tags + maxThroughput: table.?maxThroughput + throughput: table.?throughput + } + } +] + module databaseAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-databaseAccount-PrivateEndpoint-${index}' @@ -713,7 +742,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint ip address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private ip addresses of the private endpoint.') @@ -929,7 +958,7 @@ type secretsOutputType = { } type networkRestrictionsType = { - @description('Optional. Default to []. A single IPv4 address or a single IPv4 address range in CIDR format. Provided IPs must be well-formatted and cannot be contained in one of the following ranges: 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, since these are not enforceable by the IP address filter. Example of valid inputs: "23.40.210.245" or "23.40.210.0/8".') + @description('Required. A single IPv4 address or a single IPv4 address range in CIDR format. Provided IPs must be well-formatted and cannot be contained in one of the following ranges: 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, since these are not enforceable by the IP address filter. Example of valid inputs: "23.40.210.245" or "23.40.210.0/8".') ipRules: string[] @description('Optional. Default to AzureServices. Specifies the network ACL bypass for Azure services.') @@ -938,7 +967,7 @@ type networkRestrictionsType = { @description('Optional. Default to Enabled. Whether requests from Public Network are allowed.') publicNetworkAccess: ('Enabled' | 'Disabled')? - @description('Optional. Default to []. List of Virtual Network ACL rules configured for the Cosmos DB account..') + @description('Required. List of Virtual Network ACL rules configured for the Cosmos DB account..') virtualNetworkRules: { @description('Required. Resource ID of a subnet.') subnetResourceId: string diff --git a/avm/res/document-db/database-account/main.json b/avm/res/document-db/database-account/main.json index b09e8f067f..5d7b90ae1a 100644 --- a/avm/res/document-db/database-account/main.json +++ b/avm/res/document-db/database-account/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17113672202913052529" + "version": "0.30.23.60470", + "templateHash": "13300542630733457081" }, "name": "DocumentDB Database Accounts", "description": "This module deploys a DocumentDB Database Account.", @@ -236,7 +236,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -791,7 +791,7 @@ "type": "string" }, "metadata": { - "description": "Optional. Default to []. A single IPv4 address or a single IPv4 address range in CIDR format. Provided IPs must be well-formatted and cannot be contained in one of the following ranges: 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, since these are not enforceable by the IP address filter. Example of valid inputs: \"23.40.210.245\" or \"23.40.210.0/8\"." + "description": "Required. A single IPv4 address or a single IPv4 address range in CIDR format. Provided IPs must be well-formatted and cannot be contained in one of the following ranges: 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, since these are not enforceable by the IP address filter. Example of valid inputs: \"23.40.210.245\" or \"23.40.210.0/8\"." } }, "networkAclBypass": { @@ -830,7 +830,7 @@ } }, "metadata": { - "description": "Optional. Default to []. List of Virtual Network ACL rules configured for the Cosmos DB account.." + "description": "Required. List of Virtual Network ACL rules configured for the Cosmos DB account.." } } } @@ -892,7 +892,7 @@ "Standard" ], "metadata": { - "description": "Optional. Default to Standard. The offer type for the Cosmos DB database account." + "description": "Optional. Default to Standard. The offer type for the Azure Cosmos DB database account." } }, "locations": { @@ -956,7 +956,7 @@ }, "disableKeyBasedMetadataWriteAccess": { "type": "bool", - "defaultValue": false, + "defaultValue": true, "metadata": { "description": "Optional. Disable write operations on metadata resources (databases, containers, throughput) via account keys." } @@ -1029,6 +1029,13 @@ "description": "Optional. Gremlin Databases configurations." } }, + "tables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Table configurations." + } + }, "enableTelemetry": { "type": "bool", "defaultValue": true, @@ -1139,9 +1146,25 @@ }, "networkRestrictions": { "$ref": "#/definitions/networkRestrictionsType", - "nullable": true, + "defaultValue": { + "ipRules": [], + "virtualNetworkRules": [], + "publicNetworkAccess": "Disabled" + }, "metadata": { - "description": "Optional. The network configuration of this module." + "description": "Optional. The network configuration of this module. Defaults to `{ ipRules: [], virtualNetworkRules: [], publicNetworkAccess: 'Disabled' }`." + } + }, + "minimumTlsVersion": { + "type": "string", + "defaultValue": "Tls12", + "allowedValues": [ + "Tls", + "Tls11", + "Tls12" + ], + "metadata": { + "description": "Optional. Default to TLS 1.2. Enum to indicate the minimum allowed TLS version. Azure Cosmos DB for MongoDB RU and Apache Cassandra only work with TLS 1.2 or later." } } }, @@ -1214,7 +1237,7 @@ ], "kind": "[if(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('gremlinDatabases')))), 'GlobalDocumentDB', if(not(empty(parameters('mongodbDatabases'))), 'MongoDB', 'GlobalDocumentDB'))]", "backupPolicy": "[if(equals(parameters('backupPolicyType'), 'Continuous'), createObject('type', parameters('backupPolicyType'), 'continuousModeProperties', createObject('tier', parameters('backupPolicyContinuousTier'))), createObject('type', parameters('backupPolicyType'), 'periodicModeProperties', createObject('backupIntervalInMinutes', parameters('backupIntervalInMinutes'), 'backupRetentionIntervalInHours', parameters('backupRetentionIntervalInHours'), 'backupStorageRedundancy', parameters('backupStorageRedundancy'))))]", - "databaseAccountProperties": "[union(createObject('databaseAccountOfferType', parameters('databaseAccountOfferType'), 'backupPolicy', variables('backupPolicy')), if(or(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('mongodbDatabases')))), not(empty(parameters('gremlinDatabases')))), createObject('consistencyPolicy', variables('consistencyPolicy')[parameters('defaultConsistencyLevel')], 'enableMultipleWriteLocations', parameters('enableMultipleWriteLocations'), 'locations', if(empty(variables('databaseAccount_locations')), variables('defaultFailoverLocation'), variables('databaseAccount_locations')), 'ipRules', variables('ipRules'), 'virtualNetworkRules', variables('virtualNetworkRules'), 'networkAclBypass', coalesce(tryGet(parameters('networkRestrictions'), 'networkAclBypass'), 'AzureServices'), 'publicNetworkAccess', coalesce(tryGet(parameters('networkRestrictions'), 'publicNetworkAccess'), 'Enabled'), 'isVirtualNetworkFilterEnabled', or(not(empty(variables('ipRules'))), not(empty(variables('virtualNetworkRules')))), 'capabilities', variables('capabilities'), 'enableFreeTier', parameters('enableFreeTier'), 'enableAutomaticFailover', parameters('automaticFailover'), 'enableAnalyticalStorage', parameters('enableAnalyticalStorage')), createObject()), if(not(empty(parameters('sqlDatabases'))), createObject('disableLocalAuth', parameters('disableLocalAuth'), 'disableKeyBasedMetadataWriteAccess', parameters('disableKeyBasedMetadataWriteAccess')), createObject()), if(not(empty(parameters('mongodbDatabases'))), createObject('apiProperties', createObject('serverVersion', parameters('serverVersion'))), createObject()))]", + "databaseAccountProperties": "[union(createObject('databaseAccountOfferType', parameters('databaseAccountOfferType'), 'backupPolicy', variables('backupPolicy'), 'minimalTlsVersion', parameters('minimumTlsVersion')), if(or(or(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('mongodbDatabases')))), not(empty(parameters('gremlinDatabases')))), not(empty(parameters('tables')))), createObject('consistencyPolicy', variables('consistencyPolicy')[parameters('defaultConsistencyLevel')], 'enableMultipleWriteLocations', parameters('enableMultipleWriteLocations'), 'locations', if(empty(variables('databaseAccount_locations')), variables('defaultFailoverLocation'), variables('databaseAccount_locations')), 'ipRules', variables('ipRules'), 'virtualNetworkRules', variables('virtualNetworkRules'), 'networkAclBypass', coalesce(tryGet(parameters('networkRestrictions'), 'networkAclBypass'), 'AzureServices'), 'publicNetworkAccess', coalesce(tryGet(parameters('networkRestrictions'), 'publicNetworkAccess'), 'Enabled'), 'isVirtualNetworkFilterEnabled', or(not(empty(variables('ipRules'))), not(empty(variables('virtualNetworkRules')))), 'capabilities', variables('capabilities'), 'enableFreeTier', parameters('enableFreeTier'), 'enableAutomaticFailover', parameters('automaticFailover'), 'enableAnalyticalStorage', parameters('enableAnalyticalStorage')), createObject()), if(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('tables')))), createObject('disableLocalAuth', parameters('disableLocalAuth'), 'disableKeyBasedMetadataWriteAccess', parameters('disableKeyBasedMetadataWriteAccess')), createObject()), if(not(empty(parameters('mongodbDatabases'))), createObject('apiProperties', createObject('serverVersion', parameters('serverVersion'))), createObject()))]", "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", @@ -1373,8 +1396,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17028659150619761460" + "version": "0.30.23.60470", + "templateHash": "10274585444287252550" }, "name": "DocumentDB Database Account SQL Databases", "description": "This module deploys a SQL Database in a CosmosDB Account.", @@ -1506,8 +1529,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15811275148784494613" + "version": "0.30.23.60470", + "templateHash": "165408036680070575" }, "name": "DocumentDB Database Account SQL Database Containers", "description": "This module deploys a SQL Database Container in a CosmosDB Account.", @@ -1763,8 +1786,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8574173933379504173" + "version": "0.30.23.60470", + "templateHash": "13088569006752107887" }, "name": "DocumentDB Database Account SQL Role.", "description": "This module deploys SQL Role Definision and Assignment in a CosmosDB Account.", @@ -1850,8 +1873,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13173648139881140212" + "version": "0.30.23.60470", + "templateHash": "5054354703268051893" }, "name": "DocumentDB Database Account SQL Role Definitions.", "description": "This module deploys a SQL Role Definision in a CosmosDB Account.", @@ -1971,8 +1994,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "16344872287220693060" + "version": "0.30.23.60470", + "templateHash": "4561927123418147924" }, "name": "DocumentDB Database Account SQL Role Assignments.", "description": "This module deploys a SQL Role Assignment in a CosmosDB Account.", @@ -1995,7 +2018,7 @@ "type": "string", "defaultValue": "", "metadata": { - "description": "Required. Id needs to be granted." + "description": "Optional. Id needs to be granted." } }, "roleDefinitionId": { @@ -2085,8 +2108,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5589296472144391886" + "version": "0.30.23.60470", + "templateHash": "1169635175830874795" }, "name": "DocumentDB Database Account MongoDB Databases", "description": "This module deploys a MongoDB Database within a CosmosDB Account.", @@ -2188,8 +2211,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2005645426653376123" + "version": "0.30.23.60470", + "templateHash": "1358778299011674509" }, "name": "DocumentDB Database Account MongoDB Database Collections", "description": "This module deploys a MongoDB Database Collection.", @@ -2348,8 +2371,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7926803681315745584" + "version": "0.30.23.60470", + "templateHash": "14612267479855031826" }, "name": "DocumentDB Database Account Gremlin Databases", "description": "This module deploys a Gremlin Database within a CosmosDB Account.", @@ -2454,8 +2477,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9917502444704809829" + "version": "0.30.23.60470", + "templateHash": "5396990720772518636" }, "name": "DocumentDB Database Accounts Gremlin Databases Graphs", "description": "This module deploys a DocumentDB Database Accounts Gremlin Database Graph.", @@ -2596,6 +2619,137 @@ "databaseAccount" ] }, + "databaseAccount_tables": { + "copy": { + "name": "databaseAccount_tables", + "count": "[length(parameters('tables'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-table-{1}', uniqueString(deployment().name, parameters('location')), parameters('tables')[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "databaseAccountName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('tables')[copyIndex()].name]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('tables')[copyIndex()], 'tags'), parameters('tags'))]" + }, + "maxThroughput": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'maxThroughput')]" + }, + "throughput": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'throughput')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "15712676324433329983" + }, + "name": "Azure Cosmos DB account tables", + "description": "This module deploys a table within an Azure Cosmos DB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the table." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for the table." + } + }, + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Cosmos DB account. Required if the template is used in a standalone deployment." + } + }, + "maxThroughput": { + "type": "int", + "defaultValue": 4000, + "metadata": { + "description": "Optional. Represents maximum throughput, the resource can scale up to. Cannot be set together with `throughput`. If `throughput` is set to something else than -1, this autoscale setting is ignored." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Request Units per second (for example 10000). Cannot be set together with `maxThroughput`." + } + } + }, + "resources": { + "databaseAccount": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts", + "apiVersion": "2023-04-15", + "name": "[parameters('databaseAccountName')]" + }, + "table": { + "type": "Microsoft.DocumentDB/databaseAccounts/tables", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), createObject(), createObject('autoscaleSettings', if(equals(parameters('throughput'), null()), createObject('maxThroughput', parameters('maxThroughput')), null()), 'throughput', parameters('throughput')))]", + "resource": { + "id": "[parameters('name')]" + } + }, + "dependsOn": [ + "databaseAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the table." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the table." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/tables', parameters('databaseAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the table was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "databaseAccount" + ] + }, "databaseAccount_privateEndpoints": { "copy": { "name": "databaseAccount_privateEndpoints", @@ -3389,8 +3543,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "986606208324987345" + "version": "0.30.23.60470", + "templateHash": "12263717469683062316" } }, "definitions": { diff --git a/avm/res/document-db/database-account/mongodb-database/collection/main.json b/avm/res/document-db/database-account/mongodb-database/collection/main.json index 7ab4316f20..f40b7ac4c3 100644 --- a/avm/res/document-db/database-account/mongodb-database/collection/main.json +++ b/avm/res/document-db/database-account/mongodb-database/collection/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2005645426653376123" + "version": "0.30.23.60470", + "templateHash": "1358778299011674509" }, "name": "DocumentDB Database Account MongoDB Database Collections", "description": "This module deploys a MongoDB Database Collection.", diff --git a/avm/res/document-db/database-account/mongodb-database/main.json b/avm/res/document-db/database-account/mongodb-database/main.json index 5f89eca19e..dd4a34ab45 100644 --- a/avm/res/document-db/database-account/mongodb-database/main.json +++ b/avm/res/document-db/database-account/mongodb-database/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5589296472144391886" + "version": "0.30.23.60470", + "templateHash": "1169635175830874795" }, "name": "DocumentDB Database Account MongoDB Databases", "description": "This module deploys a MongoDB Database within a CosmosDB Account.", @@ -108,8 +108,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2005645426653376123" + "version": "0.30.23.60470", + "templateHash": "1358778299011674509" }, "name": "DocumentDB Database Account MongoDB Database Collections", "description": "This module deploys a MongoDB Database Collection.", diff --git a/avm/res/document-db/database-account/sql-database/container/main.json b/avm/res/document-db/database-account/sql-database/container/main.json index 2f20bcd666..8cac0c2a0e 100644 --- a/avm/res/document-db/database-account/sql-database/container/main.json +++ b/avm/res/document-db/database-account/sql-database/container/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15811275148784494613" + "version": "0.30.23.60470", + "templateHash": "165408036680070575" }, "name": "DocumentDB Database Account SQL Database Containers", "description": "This module deploys a SQL Database Container in a CosmosDB Account.", diff --git a/avm/res/document-db/database-account/sql-database/main.json b/avm/res/document-db/database-account/sql-database/main.json index 4bf3ca6f3c..f2458dc625 100644 --- a/avm/res/document-db/database-account/sql-database/main.json +++ b/avm/res/document-db/database-account/sql-database/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17028659150619761460" + "version": "0.30.23.60470", + "templateHash": "10274585444287252550" }, "name": "DocumentDB Database Account SQL Databases", "description": "This module deploys a SQL Database in a CosmosDB Account.", @@ -138,8 +138,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15811275148784494613" + "version": "0.30.23.60470", + "templateHash": "165408036680070575" }, "name": "DocumentDB Database Account SQL Database Containers", "description": "This module deploys a SQL Database Container in a CosmosDB Account.", diff --git a/avm/res/document-db/database-account/sql-role/main.json b/avm/res/document-db/database-account/sql-role/main.json index 071740e45e..9aed15aeb5 100644 --- a/avm/res/document-db/database-account/sql-role/main.json +++ b/avm/res/document-db/database-account/sql-role/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8574173933379504173" + "version": "0.30.23.60470", + "templateHash": "13088569006752107887" }, "name": "DocumentDB Database Account SQL Role.", "description": "This module deploys SQL Role Definision and Assignment in a CosmosDB Account.", @@ -91,8 +91,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13173648139881140212" + "version": "0.30.23.60470", + "templateHash": "5054354703268051893" }, "name": "DocumentDB Database Account SQL Role Definitions.", "description": "This module deploys a SQL Role Definision in a CosmosDB Account.", @@ -212,8 +212,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "16344872287220693060" + "version": "0.30.23.60470", + "templateHash": "4561927123418147924" }, "name": "DocumentDB Database Account SQL Role Assignments.", "description": "This module deploys a SQL Role Assignment in a CosmosDB Account.", @@ -236,7 +236,7 @@ "type": "string", "defaultValue": "", "metadata": { - "description": "Required. Id needs to be granted." + "description": "Optional. Id needs to be granted." } }, "roleDefinitionId": { diff --git a/avm/res/document-db/database-account/sql-role/sql-role-assignments/README.md b/avm/res/document-db/database-account/sql-role/sql-role-assignments/README.md index 5b694cd973..7697dc6a3e 100644 --- a/avm/res/document-db/database-account/sql-role/sql-role-assignments/README.md +++ b/avm/res/document-db/database-account/sql-role/sql-role-assignments/README.md @@ -21,7 +21,6 @@ This module deploys a SQL Role Assignment in a CosmosDB Account. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | Name of the SQL Role Assignment. | -| [`principalId`](#parameter-principalid) | string | Id needs to be granted. | | [`roleDefinitionId`](#parameter-roledefinitionid) | string | Id of the SQL Role Definition. | **Conditional parameters** @@ -30,6 +29,12 @@ This module deploys a SQL Role Assignment in a CosmosDB Account. | :-- | :-- | :-- | | [`databaseAccountName`](#parameter-databaseaccountname) | string | The name of the parent Database Account. Required if the template is used in a standalone deployment. | +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-principalid) | string | Id needs to be granted. | + ### Parameter: `name` Name of the SQL Role Assignment. @@ -37,14 +42,6 @@ Name of the SQL Role Assignment. - Required: Yes - Type: string -### Parameter: `principalId` - -Id needs to be granted. - -- Required: No -- Type: string -- Default: `''` - ### Parameter: `roleDefinitionId` Id of the SQL Role Definition. @@ -59,6 +56,14 @@ The name of the parent Database Account. Required if the template is used in a s - Required: Yes - Type: string +### Parameter: `principalId` + +Id needs to be granted. + +- Required: No +- Type: string +- Default: `''` + ## Outputs | Output | Type | Description | diff --git a/avm/res/document-db/database-account/sql-role/sql-role-assignments/main.bicep b/avm/res/document-db/database-account/sql-role/sql-role-assignments/main.bicep index 32c24742a9..871197381b 100644 --- a/avm/res/document-db/database-account/sql-role/sql-role-assignments/main.bicep +++ b/avm/res/document-db/database-account/sql-role/sql-role-assignments/main.bicep @@ -8,7 +8,7 @@ param databaseAccountName string @description('Required. Name of the SQL Role Assignment.') param name string -@description('Required. Id needs to be granted.') +@description('Optional. Id needs to be granted.') param principalId string = '' @description('Required. Id of the SQL Role Definition.') diff --git a/avm/res/document-db/database-account/sql-role/sql-role-assignments/main.json b/avm/res/document-db/database-account/sql-role/sql-role-assignments/main.json index 59ecc153e1..cb563bafe6 100644 --- a/avm/res/document-db/database-account/sql-role/sql-role-assignments/main.json +++ b/avm/res/document-db/database-account/sql-role/sql-role-assignments/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "16344872287220693060" + "version": "0.30.23.60470", + "templateHash": "4561927123418147924" }, "name": "DocumentDB Database Account SQL Role Assignments.", "description": "This module deploys a SQL Role Assignment in a CosmosDB Account.", @@ -28,7 +28,7 @@ "type": "string", "defaultValue": "", "metadata": { - "description": "Required. Id needs to be granted." + "description": "Optional. Id needs to be granted." } }, "roleDefinitionId": { diff --git a/avm/res/document-db/database-account/sql-role/sql-role-definitions/main.json b/avm/res/document-db/database-account/sql-role/sql-role-definitions/main.json index 2b240d1905..6a2e1eee82 100644 --- a/avm/res/document-db/database-account/sql-role/sql-role-definitions/main.json +++ b/avm/res/document-db/database-account/sql-role/sql-role-definitions/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13173648139881140212" + "version": "0.30.23.60470", + "templateHash": "5054354703268051893" }, "name": "DocumentDB Database Account SQL Role Definitions.", "description": "This module deploys a SQL Role Definision in a CosmosDB Account.", diff --git a/avm/res/document-db/database-account/table/README.md b/avm/res/document-db/database-account/table/README.md new file mode 100644 index 0000000000..56fc67d44c --- /dev/null +++ b/avm/res/document-db/database-account/table/README.md @@ -0,0 +1,81 @@ +# Azure Cosmos DB account tables `[Microsoft.DocumentDB/databaseAccounts/tables]` + +This module deploys a table within an Azure Cosmos DB Account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DocumentDB/databaseAccounts/tables` | [2023-04-15](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2023-04-15/databaseAccounts/tables) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the table. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`databaseAccountName`](#parameter-databaseaccountname) | string | The name of the parent Azure Cosmos DB account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`maxThroughput`](#parameter-maxthroughput) | int | Represents maximum throughput, the resource can scale up to. Cannot be set together with `throughput`. If `throughput` is set to something else than -1, this autoscale setting is ignored. | +| [`tags`](#parameter-tags) | object | Tags for the table. | +| [`throughput`](#parameter-throughput) | int | Request Units per second (for example 10000). Cannot be set together with `maxThroughput`. | + +### Parameter: `name` + +Name of the table. + +- Required: Yes +- Type: string + +### Parameter: `databaseAccountName` + +The name of the parent Azure Cosmos DB account. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `maxThroughput` + +Represents maximum throughput, the resource can scale up to. Cannot be set together with `throughput`. If `throughput` is set to something else than -1, this autoscale setting is ignored. + +- Required: No +- Type: int +- Default: `4000` + +### Parameter: `tags` + +Tags for the table. + +- Required: No +- Type: object + +### Parameter: `throughput` + +Request Units per second (for example 10000). Cannot be set together with `maxThroughput`. + +- Required: No +- Type: int + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the table. | +| `resourceGroupName` | string | The name of the resource group the table was created in. | +| `resourceId` | string | The resource ID of the table. | diff --git a/avm/res/document-db/database-account/table/main.bicep b/avm/res/document-db/database-account/table/main.bicep new file mode 100644 index 0000000000..d2ca33e367 --- /dev/null +++ b/avm/res/document-db/database-account/table/main.bicep @@ -0,0 +1,54 @@ +metadata name = 'Azure Cosmos DB account tables' +metadata description = 'This module deploys a table within an Azure Cosmos DB Account.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the table.') +param name string + +@description('Optional. Tags for the table.') +param tags object? + +@description('Conditional. The name of the parent Azure Cosmos DB account. Required if the template is used in a standalone deployment.') +param databaseAccountName string + +@description('Optional. Represents maximum throughput, the resource can scale up to. Cannot be set together with `throughput`. If `throughput` is set to something else than -1, this autoscale setting is ignored.') +param maxThroughput int = 4000 + +@description('Optional. Request Units per second (for example 10000). Cannot be set together with `maxThroughput`.') +param throughput int? + +resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' existing = { + name: databaseAccountName +} + +var tableOptions = contains(databaseAccount.properties.capabilities, { name: 'EnableServerless' }) + ? {} + : { + autoscaleSettings: throughput == null + ? { + maxThroughput: maxThroughput + } + : null + throughput: throughput + } + +resource table 'Microsoft.DocumentDB/databaseAccounts/tables@2023-04-15' = { + name: name + tags: tags + parent: databaseAccount + properties: { + options: tableOptions + resource: { + id: name + } + } +} + +@description('The name of the table.') +output name string = table.name + +@description('The resource ID of the table.') +output resourceId string = table.id + +@description('The name of the resource group the table was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/document-db/database-account/table/main.json b/avm/res/document-db/database-account/table/main.json new file mode 100644 index 0000000000..fc12ec0229 --- /dev/null +++ b/avm/res/document-db/database-account/table/main.json @@ -0,0 +1,96 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "15712676324433329983" + }, + "name": "Azure Cosmos DB account tables", + "description": "This module deploys a table within an Azure Cosmos DB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the table." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for the table." + } + }, + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Cosmos DB account. Required if the template is used in a standalone deployment." + } + }, + "maxThroughput": { + "type": "int", + "defaultValue": 4000, + "metadata": { + "description": "Optional. Represents maximum throughput, the resource can scale up to. Cannot be set together with `throughput`. If `throughput` is set to something else than -1, this autoscale setting is ignored." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Request Units per second (for example 10000). Cannot be set together with `maxThroughput`." + } + } + }, + "resources": { + "databaseAccount": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts", + "apiVersion": "2023-04-15", + "name": "[parameters('databaseAccountName')]" + }, + "table": { + "type": "Microsoft.DocumentDB/databaseAccounts/tables", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), createObject(), createObject('autoscaleSettings', if(equals(parameters('throughput'), null()), createObject('maxThroughput', parameters('maxThroughput')), null()), 'throughput', parameters('throughput')))]", + "resource": { + "id": "[parameters('name')]" + } + }, + "dependsOn": [ + "databaseAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the table." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the table." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/tables', parameters('databaseAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the table was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/document-db/database-account/tests/e2e/analytical/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/analytical/main.test.bicep index d8084ee5ad..9b0cd336ab 100644 --- a/avm/res/document-db/database-account/tests/e2e/analytical/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/analytical/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddaanl' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============== // // General resources diff --git a/avm/res/document-db/database-account/tests/e2e/boundedConsistency/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/boundedConsistency/main.test.bicep index ed724f3b13..da06bc091a 100644 --- a/avm/res/document-db/database-account/tests/e2e/boundedConsistency/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/boundedConsistency/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddabco' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============== // // General resources diff --git a/avm/res/document-db/database-account/tests/e2e/defaults/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/defaults/main.test.bicep index 3a1fc5b7f0..f82b846cc7 100644 --- a/avm/res/document-db/database-account/tests/e2e/defaults/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/defaults/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddamin' @description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============ // // Dependencies // diff --git a/avm/res/document-db/database-account/tests/e2e/gremlindb/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/gremlindb/main.test.bicep index 2fc70eae4b..1c3416efa0 100644 --- a/avm/res/document-db/database-account/tests/e2e/gremlindb/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/gremlindb/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddagrm' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============ // // Dependencies // diff --git a/avm/res/document-db/database-account/tests/e2e/kvSecrets/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/kvSecrets/main.test.bicep index d8fef1215b..4523b10735 100644 --- a/avm/res/document-db/database-account/tests/e2e/kvSecrets/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/kvSecrets/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddaskvs' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============== // // General resources diff --git a/avm/res/document-db/database-account/tests/e2e/managedIdentity/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/managedIdentity/main.test.bicep index f2a640a096..68c45535a2 100644 --- a/avm/res/document-db/database-account/tests/e2e/managedIdentity/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/managedIdentity/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddaumi' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============ // // Dependencies // diff --git a/avm/res/document-db/database-account/tests/e2e/mongodb/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/mongodb/main.test.bicep index ce8606f89a..3e5184830c 100644 --- a/avm/res/document-db/database-account/tests/e2e/mongodb/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/mongodb/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddamng' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============ // // Dependencies // diff --git a/avm/res/document-db/database-account/tests/e2e/multiRegion/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/multiRegion/dependencies.bicep deleted file mode 100644 index 9cce45a620..0000000000 --- a/avm/res/document-db/database-account/tests/e2e/multiRegion/dependencies.bicep +++ /dev/null @@ -1,49 +0,0 @@ -@description('Optional. The location to deploy to.') -param location string = resourceGroup().location - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -@description('Required. The name of the Deployment Script to create to get the paired region name.') -param pairedRegionScriptName string - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location -} - -resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid('msi-${location}-${managedIdentity.id}-Reader-RoleAssignment') - properties: { - principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'acdd72a7-3385-48ef-bd42-f606fba81ae7' - ) // Reader - principalType: 'ServicePrincipal' - } -} - -resource getPairedRegionScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: pairedRegionScriptName - location: location - kind: 'AzurePowerShell' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - properties: { - azPowerShellVersion: '8.0' - retentionInterval: 'P1D' - arguments: '-Location \\"${location}\\"' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Get-PairedRegion.ps1') - } - dependsOn: [ - roleAssignment - ] -} - -@description('The name of the paired region.') -output pairedRegionName string = getPairedRegionScript.properties.outputs.pairedRegionName diff --git a/avm/res/document-db/database-account/tests/e2e/multiRegion/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/multiRegion/main.test.bicep index a237081b2e..f7bd07e61b 100644 --- a/avm/res/document-db/database-account/tests/e2e/multiRegion/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/multiRegion/main.test.bicep @@ -17,23 +17,11 @@ param serviceShort string = 'dddaumr' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' - -// ============ // -// Dependencies // -// ============ // - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' - params: { - location: enforcedLocation - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - pairedRegionScriptName: 'dep-${namePrefix}-ds-${serviceShort}' - } -} +var enforcedLocation = 'australiaeast' +#disable-next-line no-hardcoded-location +var enforcedPairedLocation = 'uksouth' // ============== // // General resources @@ -68,7 +56,7 @@ module testDeployment '../../../main.bicep' = { { failoverPriority: 1 isZoneRedundant: true - locationName: nestedDependencies.outputs.pairedRegionName + locationName: enforcedPairedLocation } ] sqlDatabases: [ diff --git a/avm/res/document-db/database-account/tests/e2e/plain/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/plain/main.test.bicep index 1b78ae2598..589dee9f6e 100644 --- a/avm/res/document-db/database-account/tests/e2e/plain/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/plain/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddapln' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============== // // General resources diff --git a/avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/main.test.bicep index d9d20880fe..e7ec0e1c31 100644 --- a/avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddapres' @description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============ // // Dependencies // diff --git a/avm/res/document-db/database-account/tests/e2e/role/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/role/main.test.bicep index 737b310b7c..2227608475 100644 --- a/avm/res/document-db/database-account/tests/e2e/role/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/role/main.test.bicep @@ -17,7 +17,7 @@ param serviceShort string = 'dddarole' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location var enforcedLocation = 'eastus2' diff --git a/avm/res/document-db/database-account/tests/e2e/sqldb/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/sqldb/main.test.bicep index 4d9362e8aa..fb686fd49b 100644 --- a/avm/res/document-db/database-account/tests/e2e/sqldb/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/sqldb/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddasql' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============== // // General resources diff --git a/avm/res/document-db/database-account/tests/e2e/table/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/table/main.test.bicep new file mode 100644 index 0000000000..c8bdb0337f --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/table/main.test.bicep @@ -0,0 +1,62 @@ +targetScope = 'subscription' + +metadata name = 'API for Table' +metadata description = 'This instance deploys the module for an Azure Cosmos DB for Table account with two example tables.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-documentdb.databaseaccounts-${serviceShort}-rg' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'dddatbl' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. +#disable-next-line no-hardcoded-location +var enforcedLocation = 'eastus2' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' + params: { + location: enforcedLocation + name: '${namePrefix}${serviceShort}001' + capabilitiesToAdd: [ + 'EnableTable' + ] + tables: [ + { + name: 'tbl-dddatableminprov' + throughput: 400 + } + { + name: 'tbl-dddatableminauto' + maxThroughput: 1000 + } + ] + } + } +] diff --git a/avm/res/document-db/database-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/waf-aligned/main.test.bicep index 1084431aa2..ab2ce5d564 100644 --- a/avm/res/document-db/database-account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/waf-aligned/main.test.bicep @@ -17,9 +17,9 @@ param serviceShort string = 'dddawaf' @description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') param namePrefix string = '#_namePrefix_#' -// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +// The default pipeline is selecting random regions which don't have capacity for Azure Cosmos DB or support all Azure Cosmos DB features when creating new accounts. #disable-next-line no-hardcoded-location -var enforcedLocation = 'eastasia' +var enforcedLocation = 'eastus2' // ============ // // Dependencies // diff --git a/avm/res/document-db/database-account/version.json b/avm/res/document-db/database-account/version.json index e42c3d9e5f..0f81d22abc 100644 --- a/avm/res/document-db/database-account/version.json +++ b/avm/res/document-db/database-account/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.6", + "version": "0.8", "pathFilters": [ "./main.json" ] diff --git a/avm/res/document-db/mongo-cluster/README.md b/avm/res/document-db/mongo-cluster/README.md index 2ebb5f8479..e72f325a63 100644 --- a/avm/res/document-db/mongo-cluster/README.md +++ b/avm/res/document-db/mongo-cluster/README.md @@ -1039,15 +1039,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint ip address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private ip addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint ip address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1056,6 +1054,13 @@ A list of private ip addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/document-db/mongo-cluster/main.bicep b/avm/res/document-db/mongo-cluster/main.bicep index d4612a2a44..a06b406e0e 100644 --- a/avm/res/document-db/mongo-cluster/main.bicep +++ b/avm/res/document-db/mongo-cluster/main.bicep @@ -447,7 +447,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint ip address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private ip addresses of the private endpoint.') diff --git a/avm/res/document-db/mongo-cluster/main.json b/avm/res/document-db/mongo-cluster/main.json index 9d963be7d0..e132b34995 100644 --- a/avm/res/document-db/mongo-cluster/main.json +++ b/avm/res/document-db/mongo-cluster/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.27.1.19265", - "templateHash": "289094531739005234" + "version": "0.30.23.60470", + "templateHash": "11382084554700938270" }, "name": "Azure Cosmos DB MongoDB vCore cluster", "description": "This module deploys a Azure Cosmos DB MongoDB vCore cluster.\n\n**Note:** This module is not intended for broad, generic use, as it was designed to cater for the requirements of the AZD CLI product. Feature requests and bug fix requests are welcome if they support the development of the AZD CLI but may not be incorporated if they aim to make this module more generic than what it needs to be for its primary use case.", @@ -329,7 +329,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -845,8 +845,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.27.1.19265", - "templateHash": "11076682219298980277" + "version": "0.30.23.60470", + "templateHash": "2708665515541247345" }, "name": "Azure Cosmos DB MongoDB vCore Cluster Config FireWall Rules", "description": "This module config firewall rules for the Azure Cosmos DB MongoDB vCore cluster.", @@ -945,8 +945,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.27.1.19265", - "templateHash": "4835482779180953345" + "version": "0.30.23.60470", + "templateHash": "16142913599202614386" } }, "definitions": { diff --git a/avm/res/event-grid/domain/README.md b/avm/res/event-grid/domain/README.md index 7e0ec765a4..50092475ea 100644 --- a/avm/res/event-grid/domain/README.md +++ b/avm/res/event-grid/domain/README.md @@ -973,15 +973,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -990,6 +988,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/event-grid/domain/main.bicep b/avm/res/event-grid/domain/main.bicep index ddd2595ac3..117f7435a7 100644 --- a/avm/res/event-grid/domain/main.bicep +++ b/avm/res/event-grid/domain/main.bicep @@ -376,7 +376,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/event-grid/domain/main.json b/avm/res/event-grid/domain/main.json index f53f2e65df..cd3e750ab9 100644 --- a/avm/res/event-grid/domain/main.json +++ b/avm/res/event-grid/domain/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5221715648004087997" + "version": "0.30.23.60470", + "templateHash": "16159576400841812362" }, "name": "Event Grid Domains", "description": "This module deploys an Event Grid Domain.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -743,8 +743,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "18115448694482617097" + "version": "0.30.23.60470", + "templateHash": "1238304487498835186" }, "name": "Event Grid Domain Topics", "description": "This module deploys an Event Grid Domain Topic.", diff --git a/avm/res/event-grid/namespace/README.md b/avm/res/event-grid/namespace/README.md index 68fe8bf4f3..6c706e3a71 100644 --- a/avm/res/event-grid/namespace/README.md +++ b/avm/res/event-grid/namespace/README.md @@ -40,7 +40,7 @@ The following section provides usage examples for the module, which were used to - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) - [MQTT Broker with routing to a namespace topic](#example-3-mqtt-broker-with-routing-to-a-namespace-topic) -- [MQTT Broker with routing to a namespace topic](#example-4-mqtt-broker-with-routing-to-a-namespace-topic) +- [MQTT Broker with routing to a custom topic](#example-4-mqtt-broker-with-routing-to-a-custom-topic) - [WAF-aligned](#example-5-waf-aligned) ### Example 1: _Using only defaults_ @@ -1214,9 +1214,9 @@ param topicSpacesState = 'Enabled'

    -### Example 4: _MQTT Broker with routing to a namespace topic_ +### Example 4: _MQTT Broker with routing to a custom topic_ -This instance deploys the module as a MQTT Broker with routing to a topic within the same Eventgrid namespace. +This instance deploys the module as a MQTT Broker with routing to a custom topic.

    @@ -2356,15 +2356,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -2373,6 +2371,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/event-grid/namespace/main.bicep b/avm/res/event-grid/namespace/main.bicep index 29c68aeddc..b54cba6421 100644 --- a/avm/res/event-grid/namespace/main.bicep +++ b/avm/res/event-grid/namespace/main.bicep @@ -543,7 +543,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/event-grid/namespace/main.json b/avm/res/event-grid/namespace/main.json index 740f8c02be..cc71b84a53 100644 --- a/avm/res/event-grid/namespace/main.json +++ b/avm/res/event-grid/namespace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12641353733245664102" + "version": "0.30.23.60470", + "templateHash": "5783764026071462654" }, "name": "Event Grid Namespaces", "description": "This module deploys an Event Grid Namespace.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -1615,8 +1615,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2384224485883500454" + "version": "0.30.23.60470", + "templateHash": "13432369313513953808" }, "name": "Eventgrid Namespace Topics", "description": "This module deploys an Eventgrid Namespace Topic.", @@ -1901,8 +1901,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "484752655079146569" + "version": "0.30.23.60470", + "templateHash": "17089589089044607764" }, "name": "Event Subscriptions", "description": "This module deploys an Event Subscription.", @@ -2201,8 +2201,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12750364857938782710" + "version": "0.30.23.60470", + "templateHash": "10521341575239164612" }, "name": "Eventgrid Namespace CA Certificates", "description": "This module deploys an Eventgrid Namespace CA Certificate.", @@ -2331,8 +2331,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10456542411882263533" + "version": "0.30.23.60470", + "templateHash": "18108409387147428195" }, "name": "Eventgrid Namespace Clients", "description": "This module deploys an Eventgrid Namespace Client.", @@ -2497,8 +2497,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "16551042161872604300" + "version": "0.30.23.60470", + "templateHash": "16390720769511049629" }, "name": "Eventgrid Namespace Client Groups", "description": "This module deploys an Eventgrid Namespace Client Group.", @@ -2618,8 +2618,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13412075546334276790" + "version": "0.30.23.60470", + "templateHash": "9421201119756189566" }, "name": "Eventgrid Namespace Topic Spaces", "description": "This module deploys an Eventgrid Namespace Topic Space.", @@ -2870,8 +2870,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8789192089964505787" + "version": "0.30.23.60470", + "templateHash": "1634258312310183641" }, "name": "Eventgrid Namespace Permissions Bindings", "description": "This module deploys an Eventgrid Namespace Permission Binding.", diff --git a/avm/res/event-grid/namespace/tests/e2e/mqttnt/main.test.bicep b/avm/res/event-grid/namespace/tests/e2e/mqttnt/main.test.bicep index e2a8332ca0..ec0407199f 100644 --- a/avm/res/event-grid/namespace/tests/e2e/mqttnt/main.test.bicep +++ b/avm/res/event-grid/namespace/tests/e2e/mqttnt/main.test.bicep @@ -1,7 +1,7 @@ targetScope = 'subscription' -metadata name = 'MQTT Broker with routing to a namespace topic' -metadata description = 'This instance deploys the module as a MQTT Broker with routing to a topic within the same Eventgrid namespace.' +metadata name = 'MQTT Broker with routing to a custom topic' +metadata description = 'This instance deploys the module as a MQTT Broker with routing to a custom topic.' // ========== // // Parameters // diff --git a/avm/res/event-grid/topic/README.md b/avm/res/event-grid/topic/README.md index fcb7a52ee0..078e4194ad 100644 --- a/avm/res/event-grid/topic/README.md +++ b/avm/res/event-grid/topic/README.md @@ -1119,15 +1119,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1136,6 +1134,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/event-grid/topic/main.bicep b/avm/res/event-grid/topic/main.bicep index 9b0a660f01..1954647fa1 100644 --- a/avm/res/event-grid/topic/main.bicep +++ b/avm/res/event-grid/topic/main.bicep @@ -386,7 +386,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/event-grid/topic/main.json b/avm/res/event-grid/topic/main.json index a0b065e629..301669185f 100644 --- a/avm/res/event-grid/topic/main.json +++ b/avm/res/event-grid/topic/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12405995366615613618" + "version": "0.30.23.60470", + "templateHash": "2810622723572048404" }, "name": "Event Grid Topics", "description": "This module deploys an Event Grid Topic.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -738,8 +738,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2521126347714866146" + "version": "0.30.23.60470", + "templateHash": "1060516343519365885" }, "name": "EventGrid Topic Event Subscriptions", "description": "This module deploys an Event Grid Topic Event Subscription.", diff --git a/avm/res/event-hub/namespace/README.md b/avm/res/event-hub/namespace/README.md index 03faa22348..6aa3f6cbc8 100644 --- a/avm/res/event-hub/namespace/README.md +++ b/avm/res/event-hub/namespace/README.md @@ -1777,15 +1777,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1794,6 +1792,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/event-hub/namespace/main.bicep b/avm/res/event-hub/namespace/main.bicep index 9f203c5398..3d68d8b9e1 100644 --- a/avm/res/event-hub/namespace/main.bicep +++ b/avm/res/event-hub/namespace/main.bicep @@ -578,7 +578,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/event-hub/namespace/main.json b/avm/res/event-hub/namespace/main.json index e16a166f74..1142ef52f0 100644 --- a/avm/res/event-hub/namespace/main.json +++ b/avm/res/event-hub/namespace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15332291729708806177" + "version": "0.30.23.60470", + "templateHash": "5695254204931774513" }, "name": "Event Hub Namespaces", "description": "This module deploys an Event Hub Namespace.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -905,8 +905,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10257599829745692462" + "version": "0.30.23.60470", + "templateHash": "4370778315266456162" }, "name": "Event Hub Namespace Authorization Rule", "description": "This module deploys an Event Hub Namespace Authorization Rule.", @@ -1002,8 +1002,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11417529326547724260" + "version": "0.30.23.60470", + "templateHash": "60777592128484407" }, "name": "Event Hub Namespace Disaster Recovery Configs", "description": "This module deploys an Event Hub Namespace Disaster Recovery Config.", @@ -1118,8 +1118,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11002403097253998911" + "version": "0.30.23.60470", + "templateHash": "8801225791166116780" }, "name": "Event Hub Namespace Event Hubs", "description": "This module deploys an Event Hub Namespace Event Hub.", @@ -1543,8 +1543,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "3193397457060310848" + "version": "0.30.23.60470", + "templateHash": "3600583163344820893" }, "name": "Event Hub Namespace Event Hub Consumer Groups", "description": "This module deploys an Event Hub Namespace Event Hub Consumer Group.", @@ -1647,8 +1647,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15510112090713187287" + "version": "0.30.23.60470", + "templateHash": "5255101507494543017" }, "name": "Event Hub Namespace Event Hub Authorization Rules", "description": "This module deploys an Event Hub Namespace Event Hub Authorization Rule.", @@ -1783,8 +1783,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10667940256299428520" + "version": "0.30.23.60470", + "templateHash": "11642938165424421063" }, "name": "Event Hub Namespace Network Rule Sets", "description": "This module deploys an Event Hub Namespace Network Rule Set.", diff --git a/avm/res/fabric/capacity/README.md b/avm/res/fabric/capacity/README.md index d8f391e37b..a8975a4da6 100644 --- a/avm/res/fabric/capacity/README.md +++ b/avm/res/fabric/capacity/README.md @@ -8,12 +8,14 @@ This module deploys Fabric capacities, which provide the compute resources for a - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types | Resource Type | API Version | | :-- | :-- | +| `Microsoft.Authorization/locks` | [2016-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/locks) | | `Microsoft.Fabric/capacities` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates) | ## Usage examples @@ -25,7 +27,8 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/fabric/capacity:`. - [Using only defaults](#example-1-using-only-defaults) -- [WAF-aligned](#example-2-waf-aligned) +- [Using large parameter set.](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) ### Example 1: _Using only defaults_ @@ -102,7 +105,96 @@ param location = ''

    -### Example 2: _WAF-aligned_ +### Example 2: _Using large parameter set._ + +This instance deploys the module with most of its features enabled. + + +

    + +via Bicep module + +```bicep +module capacity 'br/public:avm/res/fabric/capacity:' = { + name: 'capacityDeployment' + params: { + // Required parameters + adminMembers: [ + '' + ] + name: 'fcmax001' + // Non-required parameters + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + } +} +``` + +
    +

    + +

    + +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminMembers": { + "value": [ + "" + ] + }, + "name": { + "value": "fcmax001" + }, + // Non-required parameters + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + } + } +} +``` + +
    +

    + +

    + +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/fabric/capacity:' + +// Required parameters +param adminMembers = [ + '' +] +param name = 'fcmax001' +// Non-required parameters +param location = '' +param lock = { + kind: 'CanNotDelete' + name: 'myCustomLockName' +} +``` + +
    +

    + +### Example 3: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. @@ -197,6 +289,7 @@ param skuName = 'F64' | :-- | :-- | :-- | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`skuName`](#parameter-skuname) | string | SKU tier of the Fabric resource. | | [`skuTier`](#parameter-skutier) | string | SKU name of the Fabric resource. | | [`tags`](#parameter-tags) | object | Tags of the resource. | @@ -231,6 +324,42 @@ Location for all resources. - Type: string - Default: `[resourceGroup().location]` +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + ### Parameter: `skuName` SKU tier of the Fabric resource. @@ -285,6 +414,14 @@ Tags of the resource. | `resourceGroupName` | string | The name of the resource group the module was deployed to. | | `resourceId` | string | The resource ID of the deployed Fabric resource. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/fabric/capacity/main.bicep b/avm/res/fabric/capacity/main.bicep index 65c6a7242d..c19347a9fe 100644 --- a/avm/res/fabric/capacity/main.bicep +++ b/avm/res/fabric/capacity/main.bicep @@ -34,6 +34,10 @@ param skuTier string = 'Fabric' @description('Required. List of admin members. Format: ["something@domain.com"].') param adminMembers array +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' +@description('Optional. The lock settings of the service.') +param lock lockType? + @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true @@ -75,6 +79,17 @@ resource fabricCapacity 'Microsoft.Fabric/capacities@2023-11-01' = { } } +resource fabricCapacity_lock 'Microsoft.Authorization/locks@2016-09-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' + ? 'Cannot delete resource or child resources.' + : 'Cannot delete or modify the resource or child resources.' + } + scope: fabricCapacity +} + // ============ // // Outputs // // ============ // diff --git a/avm/res/fabric/capacity/main.json b/avm/res/fabric/capacity/main.json index f90c00a5fc..ead274d019 100644 --- a/avm/res/fabric/capacity/main.json +++ b/avm/res/fabric/capacity/main.json @@ -6,12 +6,44 @@ "_generator": { "name": "bicep", "version": "0.30.3.12046", - "templateHash": "11718641793898572278" + "templateHash": "4050250114148213748" }, "name": "Fabric Capacities", "description": "This module deploys Fabric capacities, which provide the compute resources for all the experiences in Fabric.", "owner": "Azure/module-maintainers" }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + } + }, "parameters": { "name": { "type": "string", @@ -69,6 +101,13 @@ "description": "Required. List of admin members. Format: [\"something@domain.com\"]." } }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, "enableTelemetry": { "type": "bool", "defaultValue": true, @@ -113,6 +152,20 @@ "members": "[parameters('adminMembers')]" } } + }, + "fabricCapacity_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2016-09-01", + "scope": "[format('Microsoft.Fabric/capacities/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "fabricCapacity" + ] } }, "outputs": { diff --git a/avm/res/fabric/capacity/tests/e2e/max/main.test.bicep b/avm/res/fabric/capacity/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..bd31c44816 --- /dev/null +++ b/avm/res/fabric/capacity/tests/e2e/max/main.test.bicep @@ -0,0 +1,59 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set.' +metadata description = 'This instance deploys the module with most of its features enabled.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-fabric-capacities-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'fcmax' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +@description('Required. Email address used by resource. This value is tenant-specific and must be stored in the CI Key Vault in a secret named \'CI-adminMembersSecret\'.') +@secure() +param adminMembersSecret string = '' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + adminMembers: [ + adminMembersSecret + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + } + } +] diff --git a/avm/res/health-bot/health-bot/README.md b/avm/res/health-bot/health-bot/README.md index 073a60ffba..4689cbc03d 100644 --- a/avm/res/health-bot/health-bot/README.md +++ b/avm/res/health-bot/health-bot/README.md @@ -13,6 +13,7 @@ This module deploys an Azure Health Bot. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types @@ -485,13 +486,13 @@ The managed identity definition for this resource. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | ### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. -- Required: Yes +- Required: No - Type: array ### Parameter: `roleAssignments` @@ -613,6 +614,14 @@ Tags of the resource. | `resourceGroupName` | string | The resource group the health bot was deployed into. | | `resourceId` | string | The resource ID of the health bot. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/health-bot/health-bot/main.bicep b/avm/res/health-bot/health-bot/main.bicep index 5eadd66157..68fdc1870f 100644 --- a/avm/res/health-bot/health-bot/main.bicep +++ b/avm/res/health-bot/health-bot/main.bicep @@ -13,17 +13,20 @@ param name string @description('Required. The name of the Azure Health Bot SKU.') param sku string +import { managedIdentityOnlyUserAssignedType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityOnlyUserAssignedType? @description('Optional. Location for all resources.') param location string = resourceGroup().location +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the resource.') param tags object? @@ -137,46 +140,3 @@ output resourceId string = healthBot.id @description('The location the resource was deployed into.') output location string = healthBot.location - -// =============== // -// Definitions // -// =============== // - -type managedIdentitiesType = { - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[] -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/health-bot/health-bot/main.json b/avm/res/health-bot/health-bot/main.json index 6ee924eb9a..eb95f2d493 100644 --- a/avm/res/health-bot/health-bot/main.json +++ b/avm/res/health-bot/health-bot/main.json @@ -5,15 +5,45 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13204699140769654908" + "version": "0.30.23.60470", + "templateHash": "9706439680882910063" }, "name": "Azure Health Bots", "description": "This module deploys an Azure Health Bot.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "managedIdentityOnlyUserAssignedType": { "type": "object", "properties": { "userAssignedResourceIds": { @@ -21,110 +51,93 @@ "items": { "type": "string" }, + "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "lockType": { + "roleAssignmentType": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "kind": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { "type": "string", "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" ], "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Optional. The principal type of the assigned principal ID." } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -146,7 +159,8 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityOnlyUserAssignedType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } @@ -160,12 +174,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/healthcare-apis/workspace/README.md b/avm/res/healthcare-apis/workspace/README.md index 66c2b983fa..5210bf8332 100644 --- a/avm/res/healthcare-apis/workspace/README.md +++ b/avm/res/healthcare-apis/workspace/README.md @@ -13,6 +13,7 @@ This module deploys a Healthcare API Workspace. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Notes](#Notes) - [Data Collection](#Data-Collection) @@ -894,6 +895,14 @@ Tags of the resource. | `resourceGroupName` | string | The resource group where the workspace is deployed. | | `resourceId` | string | The resource ID of the health data services workspace. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Notes ### Parameter Usage: `iotconnectors` diff --git a/avm/res/healthcare-apis/workspace/dicomservice/README.md b/avm/res/healthcare-apis/workspace/dicomservice/README.md index f558bdc101..eefac6dcf6 100644 --- a/avm/res/healthcare-apis/workspace/dicomservice/README.md +++ b/avm/res/healthcare-apis/workspace/dicomservice/README.md @@ -22,6 +22,7 @@ This module deploys a Healthcare API Workspace DICOM Service. | Parameter | Type | Description | | :-- | :-- | :-- | +| [`corsHeaders`](#parameter-corsheaders) | array | Specify HTTP headers which can be used during the request. Use "*" for any header. | | [`name`](#parameter-name) | string | The name of the DICOM service. | **Conditional parameters** @@ -35,7 +36,6 @@ This module deploys a Healthcare API Workspace DICOM Service. | Parameter | Type | Description | | :-- | :-- | :-- | | [`corsAllowCredentials`](#parameter-corsallowcredentials) | bool | Use this setting to indicate that cookies should be included in CORS requests. | -| [`corsHeaders`](#parameter-corsheaders) | array | Specify HTTP headers which can be used during the request. Use "*" for any header. | | [`corsMaxAge`](#parameter-corsmaxage) | int | Specify how long a result from a request can be cached in seconds. Example: 600 means 10 minutes. | | [`corsMethods`](#parameter-corsmethods) | array | Specify the allowed HTTP methods. | | [`corsOrigins`](#parameter-corsorigins) | array | Specify URLs of origin sites that can access this API, or use "*" to allow access from any site. | @@ -46,6 +46,13 @@ This module deploys a Healthcare API Workspace DICOM Service. | [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | Control permission for data plane traffic coming from public networks while private endpoint is enabled. | | [`tags`](#parameter-tags) | object | Tags of the resource. | +### Parameter: `corsHeaders` + +Specify HTTP headers which can be used during the request. Use "*" for any header. + +- Required: Yes +- Type: array + ### Parameter: `name` The name of the DICOM service. @@ -68,13 +75,6 @@ Use this setting to indicate that cookies should be included in CORS requests. - Type: bool - Default: `False` -### Parameter: `corsHeaders` - -Specify HTTP headers which can be used during the request. Use "*" for any header. - -- Required: Yes -- Type: array - ### Parameter: `corsMaxAge` Specify how long a result from a request can be cached in seconds. Example: 600 means 10 minutes. diff --git a/avm/res/healthcare-apis/workspace/dicomservice/main.bicep b/avm/res/healthcare-apis/workspace/dicomservice/main.bicep index 8717b91e8f..3e970883fd 100644 --- a/avm/res/healthcare-apis/workspace/dicomservice/main.bicep +++ b/avm/res/healthcare-apis/workspace/dicomservice/main.bicep @@ -13,7 +13,7 @@ param workspaceName string @description('Optional. Specify URLs of origin sites that can access this API, or use "*" to allow access from any site.') param corsOrigins array? -@description('Optional. Specify HTTP headers which can be used during the request. Use "*" for any header.') +@description('Required. Specify HTTP headers which can be used during the request. Use "*" for any header.') param corsHeaders array @allowed([ diff --git a/avm/res/healthcare-apis/workspace/dicomservice/main.json b/avm/res/healthcare-apis/workspace/dicomservice/main.json index b08d7fd0df..337cdf0ae8 100644 --- a/avm/res/healthcare-apis/workspace/dicomservice/main.json +++ b/avm/res/healthcare-apis/workspace/dicomservice/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "1751217677948929755" + "version": "0.30.23.60470", + "templateHash": "8075255504556528583" }, "name": "Healthcare API Workspace DICOM Services", "description": "This module deploys a Healthcare API Workspace DICOM Service.", @@ -207,7 +207,7 @@ "corsHeaders": { "type": "array", "metadata": { - "description": "Optional. Specify HTTP headers which can be used during the request. Use \"*\" for any header." + "description": "Required. Specify HTTP headers which can be used during the request. Use \"*\" for any header." } }, "corsMethods": { diff --git a/avm/res/healthcare-apis/workspace/fhirservice/main.json b/avm/res/healthcare-apis/workspace/fhirservice/main.json index eb0c2c801c..2b8bc41785 100644 --- a/avm/res/healthcare-apis/workspace/fhirservice/main.json +++ b/avm/res/healthcare-apis/workspace/fhirservice/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17664239331720913904" + "version": "0.30.23.60470", + "templateHash": "14455646643849754189" }, "name": "Healthcare API Workspace FHIR Services", "description": "This module deploys a Healthcare API Workspace FHIR Service.", diff --git a/avm/res/healthcare-apis/workspace/iotconnector/README.md b/avm/res/healthcare-apis/workspace/iotconnector/README.md index 94dc443d08..3d44d39eb2 100644 --- a/avm/res/healthcare-apis/workspace/iotconnector/README.md +++ b/avm/res/healthcare-apis/workspace/iotconnector/README.md @@ -24,7 +24,6 @@ This module deploys a Healthcare API Workspace IoT Connector. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`deviceMapping`](#parameter-devicemapping) | object | The mapping JSON that determines how incoming device data is normalized. | | [`eventHubName`](#parameter-eventhubname) | string | Event Hub name to connect to. | | [`eventHubNamespaceName`](#parameter-eventhubnamespacename) | string | Namespace of the Event Hub to connect to. | | [`name`](#parameter-name) | string | The name of the MedTech service. | @@ -40,6 +39,7 @@ This module deploys a Healthcare API Workspace IoT Connector. | Parameter | Type | Description | | :-- | :-- | :-- | | [`consumerGroup`](#parameter-consumergroup) | string | Consumer group of the event hub to connected to. | +| [`deviceMapping`](#parameter-devicemapping) | object | The mapping JSON that determines how incoming device data is normalized. | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | | [`fhirdestination`](#parameter-fhirdestination) | object | FHIR Destination. | | [`location`](#parameter-location) | string | Location for all resources. | @@ -47,20 +47,6 @@ This module deploys a Healthcare API Workspace IoT Connector. | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | | [`tags`](#parameter-tags) | object | Tags of the resource. | -### Parameter: `deviceMapping` - -The mapping JSON that determines how incoming device data is normalized. - -- Required: No -- Type: object -- Default: - ```Bicep - { - template: [] - templateType: 'CollectionContent' - } - ``` - ### Parameter: `eventHubName` Event Hub name to connect to. @@ -97,6 +83,20 @@ Consumer group of the event hub to connected to. - Type: string - Default: `[parameters('name')]` +### Parameter: `deviceMapping` + +The mapping JSON that determines how incoming device data is normalized. + +- Required: No +- Type: object +- Default: + ```Bicep + { + template: [] + templateType: 'CollectionContent' + } + ``` + ### Parameter: `diagnosticSettings` The diagnostic settings of the service. diff --git a/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/README.md b/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/README.md index c27c07ed13..e3417245d4 100644 --- a/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/README.md +++ b/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/README.md @@ -21,7 +21,6 @@ This module deploys a Healthcare API Workspace IoT Connector FHIR Destination. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`destinationMapping`](#parameter-destinationmapping) | object | The mapping JSON that determines how normalized data is converted to FHIR Observations. | | [`fhirServiceResourceId`](#parameter-fhirserviceresourceid) | string | The resource identifier of the FHIR Service to connect to. | | [`name`](#parameter-name) | string | The name of the FHIR destination. | @@ -36,23 +35,10 @@ This module deploys a Healthcare API Workspace IoT Connector FHIR Destination. | Parameter | Type | Description | | :-- | :-- | :-- | +| [`destinationMapping`](#parameter-destinationmapping) | object | The mapping JSON that determines how normalized data is converted to FHIR Observations. | | [`location`](#parameter-location) | string | Location for all resources. | | [`resourceIdentityResolutionType`](#parameter-resourceidentityresolutiontype) | string | Determines how resource identity is resolved on the destination. | -### Parameter: `destinationMapping` - -The mapping JSON that determines how normalized data is converted to FHIR Observations. - -- Required: No -- Type: object -- Default: - ```Bicep - { - template: [] - templateType: 'CollectionFhir' - } - ``` - ### Parameter: `fhirServiceResourceId` The resource identifier of the FHIR Service to connect to. @@ -81,6 +67,20 @@ The name of the parent health data services workspace. Required if the template - Required: Yes - Type: string +### Parameter: `destinationMapping` + +The mapping JSON that determines how normalized data is converted to FHIR Observations. + +- Required: No +- Type: object +- Default: + ```Bicep + { + template: [] + templateType: 'CollectionFhir' + } + ``` + ### Parameter: `location` Location for all resources. diff --git a/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/main.bicep b/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/main.bicep index d42720678b..bfb87636ed 100644 --- a/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/main.bicep +++ b/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/main.bicep @@ -6,7 +6,7 @@ metadata owner = 'Azure/module-maintainers' @maxLength(24) param name string -@description('Required. The mapping JSON that determines how normalized data is converted to FHIR Observations.') +@description('Optional. The mapping JSON that determines how normalized data is converted to FHIR Observations.') param destinationMapping object = { templateType: 'CollectionFhir' template: [] diff --git a/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/main.json b/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/main.json index 87612193cc..dd32895bd1 100644 --- a/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/main.json +++ b/avm/res/healthcare-apis/workspace/iotconnector/fhirdestination/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12659357611219228021" + "version": "0.30.23.60470", + "templateHash": "9211958556323045062" }, "name": "Healthcare API Workspace IoT Connector FHIR Destinations", "description": "This module deploys a Healthcare API Workspace IoT Connector FHIR Destination.", @@ -26,7 +26,7 @@ "template": [] }, "metadata": { - "description": "Required. The mapping JSON that determines how normalized data is converted to FHIR Observations." + "description": "Optional. The mapping JSON that determines how normalized data is converted to FHIR Observations." } }, "iotConnectorName": { diff --git a/avm/res/healthcare-apis/workspace/iotconnector/main.bicep b/avm/res/healthcare-apis/workspace/iotconnector/main.bicep index 11fbb1192d..6653f1b627 100644 --- a/avm/res/healthcare-apis/workspace/iotconnector/main.bicep +++ b/avm/res/healthcare-apis/workspace/iotconnector/main.bicep @@ -19,7 +19,7 @@ param consumerGroup string = name @description('Required. Namespace of the Event Hub to connect to.') param eventHubNamespaceName string -@description('Required. The mapping JSON that determines how incoming device data is normalized.') +@description('Optional. The mapping JSON that determines how incoming device data is normalized.') param deviceMapping object = { templateType: 'CollectionContent' template: [] diff --git a/avm/res/healthcare-apis/workspace/iotconnector/main.json b/avm/res/healthcare-apis/workspace/iotconnector/main.json index 8b9a9c6bd5..c8865cad8b 100644 --- a/avm/res/healthcare-apis/workspace/iotconnector/main.json +++ b/avm/res/healthcare-apis/workspace/iotconnector/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13346867265471851551" + "version": "0.30.23.60470", + "templateHash": "960125802721112117" }, "name": "Healthcare API Workspace IoT Connectors", "description": "This module deploys a Healthcare API Workspace IoT Connector.", @@ -223,7 +223,7 @@ "template": [] }, "metadata": { - "description": "Required. The mapping JSON that determines how incoming device data is normalized." + "description": "Optional. The mapping JSON that determines how incoming device data is normalized." } }, "fhirdestination": { @@ -392,8 +392,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12659357611219228021" + "version": "0.30.23.60470", + "templateHash": "9211958556323045062" }, "name": "Healthcare API Workspace IoT Connector FHIR Destinations", "description": "This module deploys a Healthcare API Workspace IoT Connector FHIR Destination.", @@ -414,7 +414,7 @@ "template": [] }, "metadata": { - "description": "Required. The mapping JSON that determines how normalized data is converted to FHIR Observations." + "description": "Optional. The mapping JSON that determines how normalized data is converted to FHIR Observations." } }, "iotConnectorName": { diff --git a/avm/res/healthcare-apis/workspace/main.bicep b/avm/res/healthcare-apis/workspace/main.bicep index 475e814f77..743b430d3a 100644 --- a/avm/res/healthcare-apis/workspace/main.bicep +++ b/avm/res/healthcare-apis/workspace/main.bicep @@ -10,11 +10,13 @@ param name string @description('Optional. Location for all resources.') param location string = resourceGroup().location +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @allowed([ 'Disabled' @@ -247,41 +249,3 @@ output resourceGroupName string = resourceGroup().name @description('The location the resource was deployed into.') output location string = workspace.location - -// =============== // -// Definitions // -// =============== // - -type lockType = { - @sys.description('Optional. Specify the name of lock.') - name: string? - - @sys.description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @sys.description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @sys.description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @sys.description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @sys.description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @sys.description('Optional. The description of the role assignment.') - description: string? - - @sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @sys.description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @sys.description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/healthcare-apis/workspace/main.json b/avm/res/healthcare-apis/workspace/main.json index 12635c0fb4..4361adabe7 100644 --- a/avm/res/healthcare-apis/workspace/main.json +++ b/avm/res/healthcare-apis/workspace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17512289027426655191" + "version": "0.30.23.60470", + "templateHash": "17701323057909267930" }, "name": "Healthcare API Workspaces", "description": "This module deploys a Healthcare API Workspace.", @@ -36,80 +36,87 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -130,12 +137,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -382,8 +394,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17664239331720913904" + "version": "0.30.23.60470", + "templateHash": "14455646643849754189" }, "name": "Healthcare API Workspace FHIR Services", "description": "This module deploys a Healthcare API Workspace FHIR Service.", @@ -1116,8 +1128,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "1751217677948929755" + "version": "0.30.23.60470", + "templateHash": "8075255504556528583" }, "name": "Healthcare API Workspace DICOM Services", "description": "This module deploys a Healthcare API Workspace DICOM Service.", @@ -1318,7 +1330,7 @@ "corsHeaders": { "type": "array", "metadata": { - "description": "Optional. Specify HTTP headers which can be used during the request. Use \"*\" for any header." + "description": "Required. Specify HTTP headers which can be used during the request. Use \"*\" for any header." } }, "corsMethods": { @@ -1583,8 +1595,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13346867265471851551" + "version": "0.30.23.60470", + "templateHash": "960125802721112117" }, "name": "Healthcare API Workspace IoT Connectors", "description": "This module deploys a Healthcare API Workspace IoT Connector.", @@ -1801,7 +1813,7 @@ "template": [] }, "metadata": { - "description": "Required. The mapping JSON that determines how incoming device data is normalized." + "description": "Optional. The mapping JSON that determines how incoming device data is normalized." } }, "fhirdestination": { @@ -1970,8 +1982,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12659357611219228021" + "version": "0.30.23.60470", + "templateHash": "9211958556323045062" }, "name": "Healthcare API Workspace IoT Connector FHIR Destinations", "description": "This module deploys a Healthcare API Workspace IoT Connector FHIR Destination.", @@ -1992,7 +2004,7 @@ "template": [] }, "metadata": { - "description": "Required. The mapping JSON that determines how normalized data is converted to FHIR Observations." + "description": "Optional. The mapping JSON that determines how normalized data is converted to FHIR Observations." } }, "iotConnectorName": { diff --git a/avm/res/insights/component/README.md b/avm/res/insights/component/README.md index 5d3c5bd464..6a7a088be3 100644 --- a/avm/res/insights/component/README.md +++ b/avm/res/insights/component/README.md @@ -8,6 +8,7 @@ This component deploys an Application Insights instance. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types @@ -514,7 +515,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -624,7 +625,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -689,7 +690,6 @@ Linked storage account resource ID. - Required: No - Type: string -- Default: `''` ### Parameter: `location` @@ -885,6 +885,14 @@ Tags of the resource. | `resourceGroupName` | string | The resource group the application insights component was deployed into. | | `resourceId` | string | The resource ID of the application insights component. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.3.0` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/insights/component/linkedStorageAccounts/main.json b/avm/res/insights/component/linkedStorageAccounts/main.json index a5d6e69bab..9bb22a6e89 100644 --- a/avm/res/insights/component/linkedStorageAccounts/main.json +++ b/avm/res/insights/component/linkedStorageAccounts/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "216781367921725873" + "version": "0.31.34.60546", + "templateHash": "16330852520711792816" }, "name": "Application Insights Linked Storage Account", "description": "This component deploys an Application Insights Linked Storage Account.", diff --git a/avm/res/insights/component/main.bicep b/avm/res/insights/component/main.bicep index a7a3c60dca..8b00736f3e 100644 --- a/avm/res/insights/component/main.bicep +++ b/avm/res/insights/component/main.bicep @@ -25,7 +25,7 @@ param disableLocalAuth bool = false param forceCustomerStorageForProfiler bool = false @description('Optional. Linked storage account resource ID.') -param linkedStorageAccountResourceId string = '' +param linkedStorageAccountResourceId string? @description('Optional. The network access type for accessing Application Insights ingestion. - Enabled or Disabled.') @allowed([ @@ -66,8 +66,9 @@ param kind string = '' @description('Optional. Location for all Resources.') param location string = resourceGroup().location +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.3.0' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the resource.') param tags object? @@ -75,8 +76,9 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.3.0' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -160,7 +162,7 @@ module linkedStorageAccount 'linkedStorageAccounts/main.bicep' = if (!empty(link name: '${uniqueString(deployment().name, location)}-appInsights-linkedStorageAccount' params: { appInsightsName: appInsights.name - storageAccountResourceId: linkedStorageAccountResourceId + storageAccountResourceId: linkedStorageAccountResourceId ?? '' } } @@ -229,77 +231,3 @@ output instrumentationKey string = appInsights.properties.InstrumentationKey @description('Application Insights Connection String.') output connectionString string = appInsights.properties.ConnectionString - -// =============== // -// Definitions // -// =============== // - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? diff --git a/avm/res/insights/component/main.json b/avm/res/insights/component/main.json index f7b9e3a933..210dd993f9 100644 --- a/avm/res/insights/component/main.json +++ b/avm/res/insights/component/main.json @@ -5,206 +5,210 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "707617228684994883" + "version": "0.31.34.60546", + "templateHash": "2627482903423190891" }, "name": "Application Insights", "description": "This component deploys an Application Insights instance.", "owner": "Azure/module-maintainers" }, "definitions": { - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." } }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } } }, "parameters": { @@ -254,7 +258,7 @@ }, "linkedStorageAccountResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Linked storage account resource ID." } @@ -323,7 +327,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -343,7 +351,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -487,7 +499,7 @@ "value": "[parameters('name')]" }, "storageAccountResourceId": { - "value": "[parameters('linkedStorageAccountResourceId')]" + "value": "[coalesce(parameters('linkedStorageAccountResourceId'), '')]" } }, "template": { @@ -496,8 +508,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "216781367921725873" + "version": "0.31.34.60546", + "templateHash": "16330852520711792816" }, "name": "Application Insights Linked Storage Account", "description": "This component deploys an Application Insights Linked Storage Account.", diff --git a/avm/res/insights/private-link-scope/README.md b/avm/res/insights/private-link-scope/README.md index 82c8c5da93..4f0d01138d 100644 --- a/avm/res/insights/private-link-scope/README.md +++ b/avm/res/insights/private-link-scope/README.md @@ -1319,15 +1319,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1336,6 +1334,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/insights/private-link-scope/main.bicep b/avm/res/insights/private-link-scope/main.bicep index a6666eec33..5826589e02 100644 --- a/avm/res/insights/private-link-scope/main.bicep +++ b/avm/res/insights/private-link-scope/main.bicep @@ -326,7 +326,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/insights/private-link-scope/main.json b/avm/res/insights/private-link-scope/main.json index ecb92303a1..289199a4d8 100644 --- a/avm/res/insights/private-link-scope/main.json +++ b/avm/res/insights/private-link-scope/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "5947451992668490696" + "version": "0.30.23.60470", + "templateHash": "11811489211976276991" }, "name": "Azure Monitor Private Link Scopes", "description": "This module deploys an Azure Monitor Private Link Scope.", @@ -214,7 +214,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -601,8 +601,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "16277811786602972091" + "version": "0.30.23.60470", + "templateHash": "2722460902727903283" }, "name": "Private Link Scope Scoped Resources", "description": "This module deploys a Private Link Scope Scoped Resource.", diff --git a/avm/res/key-vault/vault/README.md b/avm/res/key-vault/vault/README.md index 1155d01736..db1f083092 100644 --- a/avm/res/key-vault/vault/README.md +++ b/avm/res/key-vault/vault/README.md @@ -2477,15 +2477,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -2494,6 +2492,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/key-vault/vault/main.bicep b/avm/res/key-vault/vault/main.bicep index 12df3e45a3..03b79b0c01 100644 --- a/avm/res/key-vault/vault/main.bicep +++ b/avm/res/key-vault/vault/main.bicep @@ -512,7 +512,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index a6769b9cb6..f772624dfc 100644 --- a/avm/res/key-vault/vault/main.json +++ b/avm/res/key-vault/vault/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "4499855760252174192" + "templateHash": "16644955327529459184" }, "name": "Key Vaults", "description": "This module deploys a Key Vault.", @@ -309,7 +309,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { diff --git a/avm/res/kusto/cluster/README.md b/avm/res/kusto/cluster/README.md index 6c6e0b22ed..407f17b4fa 100644 --- a/avm/res/kusto/cluster/README.md +++ b/avm/res/kusto/cluster/README.md @@ -798,7 +798,7 @@ The Kusto Cluster's accepted audiences. - Type: array - Default: `[]` -**Optional parameters** +**Required parameters** | Parameter | Type | Description | | :-- | :-- | :-- | @@ -1264,7 +1264,7 @@ Enables system assigned managed identity on the resource. The resource id(s) to assign to the resource. -- Required: Yes +- Required: No - Type: array ### Parameter: `principalAssignments` @@ -1341,15 +1341,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1358,6 +1356,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/kusto/cluster/main.bicep b/avm/res/kusto/cluster/main.bicep index e1372dca57..01c343a0d5 100644 --- a/avm/res/kusto/cluster/main.bicep +++ b/avm/res/kusto/cluster/main.bicep @@ -391,7 +391,7 @@ output privateEndpoints array = [ // =============== // type acceptedAudienceType = { - @description('Optional. GUID or valid URL representing an accepted audience.') + @description('Required. GUID or valid URL representing an accepted audience.') value: string }? @@ -488,7 +488,7 @@ type managedIdentitiesType = { systemAssigned: bool? @description('Optional. The resource id(s) to assign to the resource.') - userAssignedResourceIds: string[] + userAssignedResourceIds: string[]? }? type privateEndpointType = { @@ -531,7 +531,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/kusto/cluster/main.json b/avm/res/kusto/cluster/main.json index 2c06ed215d..edb61b98fe 100644 --- a/avm/res/kusto/cluster/main.json +++ b/avm/res/kusto/cluster/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17272299626990757362" + "version": "0.30.23.60470", + "templateHash": "8362793153324787983" }, "name": "Kusto Cluster", "description": "This module deploys a Kusto Cluster.", @@ -19,7 +19,7 @@ "value": { "type": "string", "metadata": { - "description": "Optional. GUID or valid URL representing an accepted audience." + "description": "Required. GUID or valid URL representing an accepted audience." } } }, @@ -264,6 +264,7 @@ "items": { "type": "string" }, + "nullable": true, "metadata": { "description": "Optional. The resource id(s) to assign to the resource." } @@ -373,7 +374,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -1079,8 +1080,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15388375145433684348" + "version": "0.30.23.60470", + "templateHash": "157221949480329840" }, "name": "Kusto Cluster Principal Assignments", "description": "This module deploys a Kusto Cluster Principal Assignment.", diff --git a/avm/res/machine-learning-services/workspace/README.md b/avm/res/machine-learning-services/workspace/README.md index 5257a24585..310e4097f9 100644 --- a/avm/res/machine-learning-services/workspace/README.md +++ b/avm/res/machine-learning-services/workspace/README.md @@ -2174,15 +2174,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -2191,6 +2189,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/machine-learning-services/workspace/main.bicep b/avm/res/machine-learning-services/workspace/main.bicep index beadb6aa63..7ec6ee71d0 100644 --- a/avm/res/machine-learning-services/workspace/main.bicep +++ b/avm/res/machine-learning-services/workspace/main.bicep @@ -540,7 +540,7 @@ type privateEndpointType = { @sys.description('Optional. Custom DNS configurations.') customDnsConfigs: { - @sys.description('Required. Fqdn that resolves to private endpoint IP address.') + @sys.description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @sys.description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/machine-learning-services/workspace/main.json b/avm/res/machine-learning-services/workspace/main.json index 188ff7e44c..54b4c5b3f5 100644 --- a/avm/res/machine-learning-services/workspace/main.json +++ b/avm/res/machine-learning-services/workspace/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "13428062064493278756" + "templateHash": "1720825561395705058" }, "name": "Machine Learning Services Workspaces", "description": "This module deploys a Machine Learning Services Workspace.", @@ -236,7 +236,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { diff --git a/avm/res/managed-services/registration-definition/main.bicep b/avm/res/managed-services/registration-definition/main.bicep index 5a25838cb1..6b8ee11127 100644 --- a/avm/res/managed-services/registration-definition/main.bicep +++ b/avm/res/managed-services/registration-definition/main.bicep @@ -96,6 +96,8 @@ output assignmentResourceId string = empty(resourceGroupName) // Definitions // // ================ // +@export() +@description('Authorization object describing the access Azure Active Directory principals in the managedBy tenant will receive on the delegated resource in the managed tenant.') type authorizationType = { @description('Conditional. The list of role definition ids which define all the permissions that the user in the authorization can assign to other principals. Required if the `roleDefinitionId` refers to the User Access Administrator Role.') delegatedRoleDefinitionIds: string[]? diff --git a/avm/res/managed-services/registration-definition/main.json b/avm/res/managed-services/registration-definition/main.json index d1e41f4df3..7176bf7ad8 100644 --- a/avm/res/managed-services/registration-definition/main.json +++ b/avm/res/managed-services/registration-definition/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "6598987839511353461" + "version": "0.30.23.60470", + "templateHash": "806800728084876706" }, "name": "Registration Definitions", "description": "This module deploys a `Registration Definition` and a `Registration Assignment` (often referred to as 'Lighthouse' or 'resource delegation') on a subscription or resource group scope.\nThis 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.\nThe 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.", @@ -45,6 +45,10 @@ "description": "Required. The identifier of the Azure built-in role that defines the permissions that the Azure Active Directory principal will have on the projected scope." } } + }, + "metadata": { + "__bicep_export!": true, + "description": "Authorization object describing the access Azure Active Directory principals in the managedBy tenant will receive on the delegated resource in the managed tenant." } } }, @@ -175,8 +179,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "17889456379146479598" + "version": "0.30.23.60470", + "templateHash": "1358545064505499503" }, "name": "Registration Assignment", "description": "Create a registration assignment.", diff --git a/avm/res/net-app/net-app-account/README.md b/avm/res/net-app/net-app-account/README.md index 3a41e6dc96..2cfd330976 100644 --- a/avm/res/net-app/net-app-account/README.md +++ b/avm/res/net-app/net-app-account/README.md @@ -1226,7 +1226,7 @@ The managed identity definition for this resource. The resource ID(s) to assign to the resource. -- Required: Yes +- Required: No - Type: array ### Parameter: `roleAssignments` diff --git a/avm/res/net-app/net-app-account/backup-policies/README.md b/avm/res/net-app/net-app-account/backup-policies/README.md index 6756951c04..16fed5137d 100644 --- a/avm/res/net-app/net-app-account/backup-policies/README.md +++ b/avm/res/net-app/net-app-account/backup-policies/README.md @@ -20,7 +20,10 @@ This module deploys a Backup Policy for Azure NetApp File. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`backupPolicyName`](#parameter-backuppolicyname) | string | The name of the backup policy. | +| [`backupPolicyLocation`](#parameter-backuppolicylocation) | string | The location of the backup policy. Required if the template is used in a standalone deployment. | +| [`dailyBackupsToKeep`](#parameter-dailybackupstokeep) | int | The daily backups to keep. | +| [`monthlyBackupsToKeep`](#parameter-monthlybackupstokeep) | int | The monthly backups to keep. | +| [`weeklyBackupsToKeep`](#parameter-weeklybackupstokeep) | int | The weekly backups to keep. | **Conditional parameters** @@ -33,33 +36,7 @@ This module deploys a Backup Policy for Azure NetApp File. | Parameter | Type | Description | | :-- | :-- | :-- | | [`backupEnabled`](#parameter-backupenabled) | bool | Indicates whether the backup policy is enabled. | -| [`backupPolicyLocation`](#parameter-backuppolicylocation) | string | The location of the backup policy. Required if the template is used in a standalone deployment. | -| [`dailyBackupsToKeep`](#parameter-dailybackupstokeep) | int | The daily backups to keep. | -| [`monthlyBackupsToKeep`](#parameter-monthlybackupstokeep) | int | The monthly backups to keep. | -| [`weeklyBackupsToKeep`](#parameter-weeklybackupstokeep) | int | The weekly backups to keep. | - -### Parameter: `backupPolicyName` - -The name of the backup policy. - -- Required: No -- Type: string -- Default: `'backupPolicy'` - -### Parameter: `netAppAccountName` - -The name of the parent NetApp account. Required if the template is used in a standalone deployment. - -- Required: Yes -- Type: string - -### Parameter: `backupEnabled` - -Indicates whether the backup policy is enabled. - -- Required: No -- Type: bool -- Default: `False` +| [`backupPolicyName`](#parameter-backuppolicyname) | string | The name of the backup policy. | ### Parameter: `backupPolicyLocation` @@ -89,6 +66,29 @@ The weekly backups to keep. - Required: Yes - Type: int +### Parameter: `netAppAccountName` + +The name of the parent NetApp account. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `backupEnabled` + +Indicates whether the backup policy is enabled. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `backupPolicyName` + +The name of the backup policy. + +- Required: No +- Type: string +- Default: `'backupPolicy'` + ## Outputs | Output | Type | Description | diff --git a/avm/res/net-app/net-app-account/backup-policies/main.bicep b/avm/res/net-app/net-app-account/backup-policies/main.bicep index 5a254eadfb..6fa1fe7f74 100644 --- a/avm/res/net-app/net-app-account/backup-policies/main.bicep +++ b/avm/res/net-app/net-app-account/backup-policies/main.bicep @@ -5,19 +5,19 @@ metadata owner = 'Azure/module-maintainers' @description('Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment.') param netAppAccountName string -@description('Required. The name of the backup policy.') +@description('Optional. The name of the backup policy.') param backupPolicyName string = 'backupPolicy' -@description('Optional. The location of the backup policy. Required if the template is used in a standalone deployment.') +@description('Required. The location of the backup policy. Required if the template is used in a standalone deployment.') param backupPolicyLocation string -@description('Optional. The daily backups to keep.') +@description('Required. The daily backups to keep.') param dailyBackupsToKeep int -@description('Optional. The monthly backups to keep.') +@description('Required. The monthly backups to keep.') param monthlyBackupsToKeep int -@description('Optional. The weekly backups to keep.') +@description('Required. The weekly backups to keep.') param weeklyBackupsToKeep int @description('Optional. Indicates whether the backup policy is enabled.') diff --git a/avm/res/net-app/net-app-account/backup-policies/main.json b/avm/res/net-app/net-app-account/backup-policies/main.json index 315e53cdee..0f68e10321 100644 --- a/avm/res/net-app/net-app-account/backup-policies/main.json +++ b/avm/res/net-app/net-app-account/backup-policies/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "16399924782439066553" + "version": "0.30.23.60470", + "templateHash": "13036318518380500677" }, "name": "Azure NetApp Files Backup Policy", "description": "This module deploys a Backup Policy for Azure NetApp File.", @@ -22,31 +22,31 @@ "type": "string", "defaultValue": "backupPolicy", "metadata": { - "description": "Required. The name of the backup policy." + "description": "Optional. The name of the backup policy." } }, "backupPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The location of the backup policy. Required if the template is used in a standalone deployment." + "description": "Required. The location of the backup policy. Required if the template is used in a standalone deployment." } }, "dailyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The daily backups to keep." + "description": "Required. The daily backups to keep." } }, "monthlyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The monthly backups to keep." + "description": "Required. The monthly backups to keep." } }, "weeklyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The weekly backups to keep." + "description": "Required. The weekly backups to keep." } }, "backupEnabled": { diff --git a/avm/res/net-app/net-app-account/capacity-pool/README.md b/avm/res/net-app/net-app-account/capacity-pool/README.md index 888ae5f9ef..ce4e635136 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/README.md +++ b/avm/res/net-app/net-app-account/capacity-pool/README.md @@ -28,7 +28,6 @@ This module deploys an Azure NetApp Files Capacity Pool. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | The name of the capacity pool. | -| [`networkFeatures`](#parameter-networkfeatures) | string | Network features available to the volume, or current state of update (Basic/Standard). | | [`size`](#parameter-size) | int | Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). | **Conditional parameters** @@ -57,14 +56,6 @@ The name of the capacity pool. - Required: Yes - Type: string -### Parameter: `networkFeatures` - -Network features available to the volume, or current state of update (Basic/Standard). - -- Required: No -- Type: string -- Default: `'Standard'` - ### Parameter: `size` Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/main.bicep index 05ee747227..c8fa6c36f5 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/main.bicep +++ b/avm/res/net-app/net-app-account/capacity-pool/main.bicep @@ -23,9 +23,6 @@ param tags object? ]) param serviceLevel string = 'Standard' -@description('Required. Network features available to the volume, or current state of update (Basic/Standard).') -param networkFeatures 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 @@ -122,7 +119,6 @@ module capacityPool_volumes 'volume/main.bicep' = [ remoteVolumeRegion: volume.?remoteVolumeRegion ?? '' remoteVolumeResourceId: volume.?remoteVolumeResourceId ?? '' replicationSchedule: volume.?replicationSchedule ?? '' - snapshotPolicyId: volume.?snapshotPolicyId ?? '' snapshotPolicyName: volume.?snapshotPolicyName ?? 'snapshotPolicy' snapshotPolicyLocation: volume.?snapshotPolicyLocation ?? '' snapEnabled: volume.?snapEnabled ?? false diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.json b/avm/res/net-app/net-app-account/capacity-pool/main.json index 51024b061a..6266575c14 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/main.json +++ b/avm/res/net-app/net-app-account/capacity-pool/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "5120059204101466005" + "version": "0.30.23.60470", + "templateHash": "1966206032457552782" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -127,13 +127,6 @@ "description": "Optional. The pool service level." } }, - "networkFeatures": { - "type": "string", - "defaultValue": "Standard", - "metadata": { - "description": "Required. Network features available to the volume, or current state of update (Basic/Standard)." - } - }, "size": { "type": "int", "metadata": { @@ -327,9 +320,6 @@ "replicationSchedule": { "value": "[coalesce(tryGet(parameters('volumes')[copyIndex()], 'replicationSchedule'), '')]" }, - "snapshotPolicyId": { - "value": "[coalesce(tryGet(parameters('volumes')[copyIndex()], 'snapshotPolicyId'), '')]" - }, "snapshotPolicyName": { "value": "[coalesce(tryGet(parameters('volumes')[copyIndex()], 'snapshotPolicyName'), 'snapshotPolicy')]" }, @@ -446,8 +436,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "3878108397799577614" + "version": "0.30.23.60470", + "templateHash": "7267638032222261061" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", @@ -544,13 +534,13 @@ "coolAccess": { "type": "bool", "metadata": { - "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + "description": "Required. If enabled (true) the pool can contain cool Access enabled volumes." } }, "coolnessPeriod": { "type": "int", "metadata": { - "description": "Optional. Specifies the number of days after which data that is not accessed by clients will be tiered." + "description": "Required. Specifies the number of days after which data that is not accessed by clients will be tiered." } }, "coolAccessRetrievalPolicy": { @@ -563,37 +553,37 @@ "encryptionKeySource": { "type": "string", "metadata": { - "description": "Optional. The source of the encryption key." + "description": "Required. The source of the encryption key." } }, "keyVaultPrivateEndpointResourceId": { "type": "string", "metadata": { - "description": "Optional. The resource ID of the key vault private endpoint." + "description": "Required. The resource ID of the key vault private endpoint." } }, "endpointType": { "type": "string", "metadata": { - "description": "Optional. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst)." + "description": "Required. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst)." } }, "remoteVolumeRegion": { "type": "string", "metadata": { - "description": "Optional. The remote region for the other end of the Volume Replication." + "description": "Required. The remote region for the other end of the Volume Replication." } }, "remoteVolumeResourceId": { "type": "string", "metadata": { - "description": "Optional. The resource ID of the remote volume." + "description": "Required. The resource ID of the remote volume." } }, "replicationSchedule": { "type": "string", "metadata": { - "description": "Optional. The replication schedule for the volume." + "description": "Required. The replication schedule for the volume." } }, "backupEnabled": { @@ -613,103 +603,103 @@ "dailyHour": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot hour." + "description": "Required. The daily snapshot hour." } }, "dailyMinute": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot minute." + "description": "Required. The daily snapshot minute." } }, "dailySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot count to keep." + "description": "Required. Daily snapshot count to keep." } }, "dailyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot used bytes." + "description": "Required. Daily snapshot used bytes." } }, "hourlyMinute": { "type": "int", "metadata": { - "description": "Optional. The hourly snapshot minute." + "description": "Required. The hourly snapshot minute." } }, "hourlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot count to keep." + "description": "Required. Hourly snapshot count to keep." } }, "hourlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot used bytes." + "description": "Required. Hourly snapshot used bytes." } }, "daysOfMonth": { "type": "string", "metadata": { - "description": "Optional. The monthly snapshot day." + "description": "Required. The monthly snapshot day." } }, "monthlyHour": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot hour." + "description": "Required. The monthly snapshot hour." } }, "monthlyMinute": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot minute." + "description": "Required. The monthly snapshot minute." } }, "monthlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot count to keep." + "description": "Required. Monthly snapshot count to keep." } }, "monthlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot used bytes." + "description": "Required. Monthly snapshot used bytes." } }, "weeklyDay": { "type": "string", "metadata": { - "description": "Optional. The weekly snapshot day." + "description": "Required. The weekly snapshot day." } }, "weeklyHour": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot hour." + "description": "Required. The weekly snapshot hour." } }, "weeklyMinute": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot minute." + "description": "Required. The weekly snapshot minute." } }, "weeklySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot count to keep." + "description": "Required. Weekly snapshot count to keep." } }, "weeklyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot used bytes." + "description": "Required. Weekly snapshot used bytes." } }, "snapEnabled": { @@ -722,25 +712,25 @@ "snapshotPolicyName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot policy." + "description": "Required. The name of the snapshot policy." } }, "dailyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The daily backups to keep." + "description": "Required. The daily backups to keep." } }, "monthlyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The monthly backups to keep." + "description": "Required. The monthly backups to keep." } }, "weeklyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The weekly backups to keep." + "description": "Required. The weekly backups to keep." } }, "backupVaultName": { @@ -760,43 +750,37 @@ "backupName": { "type": "string", "metadata": { - "description": "Optional. The name of the backup." + "description": "Required. The name of the backup." } }, "backupLabel": { "type": "string", "metadata": { - "description": "Optional. The label of the backup." + "description": "Required. The label of the backup." } }, "useExistingSnapshot": { "type": "bool", "metadata": { - "description": "Optional. Indicates whether to use an existing snapshot." + "description": "Required. Indicates whether to use an existing snapshot." } }, "snapshotName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot." - } - }, - "snapshotPolicyId": { - "type": "string", - "metadata": { - "description": "Optional. The snapshot Policy id." + "description": "Required. The name of the snapshot." } }, "volumeResourceId": { "type": "string", "metadata": { - "description": "Optional. The resource ID of the volume." + "description": "Required. The resource ID of the volume." } }, "volumeType": { "type": "string", "metadata": { - "description": "Optional. The type of the volume. DataProtection volumes are used for replication." + "description": "Required. The type of the volume. DataProtection volumes are used for replication." } }, "name": { @@ -831,13 +815,13 @@ "backupPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The backup policy location." + "description": "Required. The backup policy location." } }, "snapshotPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The location of snashot policies." + "description": "Required. The location of snashot policies." } }, "serviceLevel": { @@ -908,7 +892,7 @@ "backupVaultId": { "type": "string", "metadata": { - "description": "Optional. The Id of the Backup Vault." + "description": "Required. The Id of the Backup Vault." } }, "replicationEnabled": { @@ -1045,8 +1029,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "16399924782439066553" + "version": "0.30.23.60470", + "templateHash": "13036318518380500677" }, "name": "Azure NetApp Files Backup Policy", "description": "This module deploys a Backup Policy for Azure NetApp File.", @@ -1063,31 +1047,31 @@ "type": "string", "defaultValue": "backupPolicy", "metadata": { - "description": "Required. The name of the backup policy." + "description": "Optional. The name of the backup policy." } }, "backupPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The location of the backup policy. Required if the template is used in a standalone deployment." + "description": "Required. The location of the backup policy. Required if the template is used in a standalone deployment." } }, "dailyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The daily backups to keep." + "description": "Required. The daily backups to keep." } }, "monthlyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The monthly backups to keep." + "description": "Required. The monthly backups to keep." } }, "weeklyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The weekly backups to keep." + "description": "Required. The weekly backups to keep." } }, "backupEnabled": { @@ -1216,8 +1200,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "17076752505050697613" + "version": "0.30.23.60470", + "templateHash": "12832989826838310090" }, "name": "Azure NetApp Files Snapshot Policy", "description": "This module deploys a Snapshot Policy for an Azure NetApp File.", @@ -1233,7 +1217,7 @@ "snapshotPolicyName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot policy." + "description": "Required. The name of the snapshot policy." } }, "snapshotPolicyLocation": { @@ -1246,103 +1230,103 @@ "dailyHour": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot hour." + "description": "Required. The daily snapshot hour." } }, "dailyMinute": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot minute." + "description": "Required. The daily snapshot minute." } }, "dailySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot count to keep." + "description": "Required. Daily snapshot count to keep." } }, "dailyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot used bytes." + "description": "Required. Daily snapshot used bytes." } }, "hourlyMinute": { "type": "int", "metadata": { - "description": "Optional. The hourly snapshot minute." + "description": "Required. The hourly snapshot minute." } }, "hourlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot count to keep." + "description": "Required. Hourly snapshot count to keep." } }, "hourlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot used bytes." + "description": "Required. Hourly snapshot used bytes." } }, "daysOfMonth": { "type": "string", "metadata": { - "description": "Optional. The monthly snapshot day." + "description": "Required. The monthly snapshot day." } }, "monthlyHour": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot hour." + "description": "Required. The monthly snapshot hour." } }, "monthlyMinute": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot minute." + "description": "Required. The monthly snapshot minute." } }, "monthlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot count to keep." + "description": "Required. Monthly snapshot count to keep." } }, "monthlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot used bytes." + "description": "Required. Monthly snapshot used bytes." } }, "weeklyDay": { "type": "string", "metadata": { - "description": "Optional. The weekly snapshot day." + "description": "Required. The weekly snapshot day." } }, "weeklyHour": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot hour." + "description": "Required. The weekly snapshot hour." } }, "weeklyMinute": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot minute." + "description": "Required. The weekly snapshot minute." } }, "weeklySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot count to keep." + "description": "Required. Weekly snapshot count to keep." } }, "weeklyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot used bytes." + "description": "Required. Weekly snapshot used bytes." } }, "snapEnabled": { diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/README.md b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md index de7e5a1c46..a1f27ddbfd 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/README.md +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md @@ -26,33 +26,12 @@ This module deploys an Azure NetApp Files Capacity Pool Volume. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-name) | string | The name of the pool volume. | -| [`subnetResourceId`](#parameter-subnetresourceid) | string | The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. | -| [`usageThreshold`](#parameter-usagethreshold) | int | Maximum storage quota allowed for a file system in bytes. | - -**Conditional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`capacityPoolName`](#parameter-capacitypoolname) | string | The name of the parent capacity pool. Required if the template is used in a standalone deployment. | -| [`netAppAccountName`](#parameter-netappaccountname) | string | The name of the parent NetApp account. Required if the template is used in a standalone deployment. | - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`backupEnabled`](#parameter-backupenabled) | bool | Indicates whether the backup policy is enabled. | | [`backupLabel`](#parameter-backuplabel) | string | The label of the backup. | | [`backupName`](#parameter-backupname) | string | The name of the backup. | | [`backupPolicyLocation`](#parameter-backuppolicylocation) | string | The backup policy location. | -| [`backupPolicyName`](#parameter-backuppolicyname) | string | The name of the backup policy. | | [`backupVaultId`](#parameter-backupvaultid) | string | The Id of the Backup Vault. | -| [`backupVaultLocation`](#parameter-backupvaultlocation) | string | The location of the backup vault. | -| [`backupVaultName`](#parameter-backupvaultname) | string | The name of the backup vault. | | [`coolAccess`](#parameter-coolaccess) | bool | If enabled (true) the pool can contain cool Access enabled volumes. | -| [`coolAccessRetrievalPolicy`](#parameter-coolaccessretrievalpolicy) | string | determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read). | | [`coolnessPeriod`](#parameter-coolnessperiod) | int | Specifies the number of days after which data that is not accessed by clients will be tiered. | -| [`creationToken`](#parameter-creationtoken) | string | 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. | | [`dailyBackupsToKeep`](#parameter-dailybackupstokeep) | int | The daily backups to keep. | | [`dailyHour`](#parameter-dailyhour) | int | The daily snapshot hour. | | [`dailyMinute`](#parameter-dailyminute) | int | The daily snapshot minute. | @@ -61,31 +40,24 @@ This module deploys an Azure NetApp Files Capacity Pool Volume. | [`daysOfMonth`](#parameter-daysofmonth) | string | The monthly snapshot day. | | [`encryptionKeySource`](#parameter-encryptionkeysource) | string | The source of the encryption key. | | [`endpointType`](#parameter-endpointtype) | string | Indicates whether the local volume is the source or destination for the Volume Replication (src/dst). | -| [`exportPolicyRules`](#parameter-exportpolicyrules) | array | Export policy rules. | | [`hourlyMinute`](#parameter-hourlyminute) | int | The hourly snapshot minute. | | [`hourlySnapshotsToKeep`](#parameter-hourlysnapshotstokeep) | int | Hourly snapshot count to keep. | | [`hourlyUsedBytes`](#parameter-hourlyusedbytes) | int | Hourly snapshot used bytes. | | [`keyVaultPrivateEndpointResourceId`](#parameter-keyvaultprivateendpointresourceid) | string | The resource ID of the key vault private endpoint. | -| [`location`](#parameter-location) | string | Location of the pool volume. | | [`monthlyBackupsToKeep`](#parameter-monthlybackupstokeep) | int | The monthly backups to keep. | | [`monthlyHour`](#parameter-monthlyhour) | int | The monthly snapshot hour. | | [`monthlyMinute`](#parameter-monthlyminute) | int | The monthly snapshot minute. | | [`monthlySnapshotsToKeep`](#parameter-monthlysnapshotstokeep) | int | Monthly snapshot count to keep. | | [`monthlyUsedBytes`](#parameter-monthlyusedbytes) | int | Monthly snapshot used bytes. | -| [`networkFeatures`](#parameter-networkfeatures) | string | Network feature for the volume. | -| [`policyEnforced`](#parameter-policyenforced) | bool | If Backup policy is enforced. | -| [`protocolTypes`](#parameter-protocoltypes) | array | Set of protocol types. | +| [`name`](#parameter-name) | string | The name of the pool volume. | | [`remoteVolumeRegion`](#parameter-remotevolumeregion) | string | The remote region for the other end of the Volume Replication. | | [`remoteVolumeResourceId`](#parameter-remotevolumeresourceid) | string | The resource ID of the remote volume. | -| [`replicationEnabled`](#parameter-replicationenabled) | bool | Boolean to enable replication. | | [`replicationSchedule`](#parameter-replicationschedule) | string | The replication schedule for the volume. | -| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | -| [`serviceLevel`](#parameter-servicelevel) | string | The pool service level. Must match the one of the parent capacity pool. | -| [`snapEnabled`](#parameter-snapenabled) | bool | Indicates whether the snapshot policy is enabled. | | [`snapshotName`](#parameter-snapshotname) | string | The name of the snapshot. | -| [`snapshotPolicyId`](#parameter-snapshotpolicyid) | string | The snapshot Policy id. | | [`snapshotPolicyLocation`](#parameter-snapshotpolicylocation) | string | The location of snashot policies. | | [`snapshotPolicyName`](#parameter-snapshotpolicyname) | string | The name of the snapshot policy. | +| [`subnetResourceId`](#parameter-subnetresourceid) | string | The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. | +| [`usageThreshold`](#parameter-usagethreshold) | int | Maximum storage quota allowed for a file system in bytes. | | [`useExistingSnapshot`](#parameter-useexistingsnapshot) | bool | Indicates whether to use an existing snapshot. | | [`volumeResourceId`](#parameter-volumeresourceid) | string | The resource ID of the volume. | | [`volumeType`](#parameter-volumetype) | string | The type of the volume. DataProtection volumes are used for replication. | @@ -95,50 +67,34 @@ This module deploys an Azure NetApp Files Capacity Pool Volume. | [`weeklyMinute`](#parameter-weeklyminute) | int | The weekly snapshot minute. | | [`weeklySnapshotsToKeep`](#parameter-weeklysnapshotstokeep) | int | Weekly snapshot count to keep. | | [`weeklyUsedBytes`](#parameter-weeklyusedbytes) | int | Weekly snapshot used bytes. | -| [`zones`](#parameter-zones) | array | Zone where the volume will be placed. | - -### Parameter: `name` - -The name of the pool volume. - -- Required: Yes -- Type: string - -### Parameter: `subnetResourceId` - -The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. - -- Required: Yes -- Type: string - -### Parameter: `usageThreshold` - -Maximum storage quota allowed for a file system in bytes. - -- Required: Yes -- Type: int - -### Parameter: `capacityPoolName` - -The name of the parent capacity pool. Required if the template is used in a standalone deployment. -- Required: Yes -- Type: string - -### Parameter: `netAppAccountName` - -The name of the parent NetApp account. Required if the template is used in a standalone deployment. - -- Required: Yes -- Type: string +**Conditional parameters** -### Parameter: `backupEnabled` +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacityPoolName`](#parameter-capacitypoolname) | string | The name of the parent capacity pool. Required if the template is used in a standalone deployment. | +| [`netAppAccountName`](#parameter-netappaccountname) | string | The name of the parent NetApp account. Required if the template is used in a standalone deployment. | -Indicates whether the backup policy is enabled. +**Optional parameters** -- Required: No -- Type: bool -- Default: `False` +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`backupEnabled`](#parameter-backupenabled) | bool | Indicates whether the backup policy is enabled. | +| [`backupPolicyName`](#parameter-backuppolicyname) | string | The name of the backup policy. | +| [`backupVaultLocation`](#parameter-backupvaultlocation) | string | The location of the backup vault. | +| [`backupVaultName`](#parameter-backupvaultname) | string | The name of the backup vault. | +| [`coolAccessRetrievalPolicy`](#parameter-coolaccessretrievalpolicy) | string | determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read). | +| [`creationToken`](#parameter-creationtoken) | string | 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. | +| [`exportPolicyRules`](#parameter-exportpolicyrules) | array | Export policy rules. | +| [`location`](#parameter-location) | string | Location of the pool volume. | +| [`networkFeatures`](#parameter-networkfeatures) | string | Network feature for the volume. | +| [`policyEnforced`](#parameter-policyenforced) | bool | If Backup policy is enforced. | +| [`protocolTypes`](#parameter-protocoltypes) | array | Set of protocol types. | +| [`replicationEnabled`](#parameter-replicationenabled) | bool | Boolean to enable replication. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`serviceLevel`](#parameter-servicelevel) | string | The pool service level. Must match the one of the parent capacity pool. | +| [`snapEnabled`](#parameter-snapenabled) | bool | Indicates whether the snapshot policy is enabled. | +| [`zones`](#parameter-zones) | array | Zone where the volume will be placed. | ### Parameter: `backupLabel` @@ -161,14 +117,6 @@ The backup policy location. - Required: Yes - Type: string -### Parameter: `backupPolicyName` - -The name of the backup policy. - -- Required: No -- Type: string -- Default: `'backupPolicy'` - ### Parameter: `backupVaultId` The Id of the Backup Vault. @@ -176,22 +124,6 @@ The Id of the Backup Vault. - Required: Yes - Type: string -### Parameter: `backupVaultLocation` - -The location of the backup vault. - -- Required: No -- Type: string -- Default: `[resourceGroup().location]` - -### Parameter: `backupVaultName` - -The name of the backup vault. - -- Required: No -- Type: string -- Default: `'vault'` - ### Parameter: `coolAccess` If enabled (true) the pool can contain cool Access enabled volumes. @@ -199,14 +131,6 @@ If enabled (true) the pool can contain cool Access enabled volumes. - Required: Yes - Type: bool -### Parameter: `coolAccessRetrievalPolicy` - -determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read). - -- Required: No -- Type: string -- Default: `'Default'` - ### Parameter: `coolnessPeriod` Specifies the number of days after which data that is not accessed by clients will be tiered. @@ -214,14 +138,6 @@ Specifies the number of days after which data that is not accessed by clients wi - Required: Yes - Type: int -### Parameter: `creationToken` - -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. - -- Required: No -- Type: string -- Default: `[parameters('name')]` - ### Parameter: `dailyBackupsToKeep` The daily backups to keep. @@ -278,14 +194,6 @@ Indicates whether the local volume is the source or destination for the Volume R - Required: Yes - Type: string -### Parameter: `exportPolicyRules` - -Export policy rules. - -- Required: No -- Type: array -- Default: `[]` - ### Parameter: `hourlyMinute` The hourly snapshot minute. @@ -314,14 +222,6 @@ The resource ID of the key vault private endpoint. - Required: Yes - Type: string -### Parameter: `location` - -Location of the pool volume. - -- Required: No -- Type: string -- Default: `[resourceGroup().location]` - ### Parameter: `monthlyBackupsToKeep` The monthly backups to keep. @@ -357,6 +257,210 @@ Monthly snapshot used bytes. - Required: Yes - Type: int +### Parameter: `name` + +The name of the pool volume. + +- Required: Yes +- Type: string + +### Parameter: `remoteVolumeRegion` + +The remote region for the other end of the Volume Replication. + +- Required: Yes +- Type: string + +### Parameter: `remoteVolumeResourceId` + +The resource ID of the remote volume. + +- Required: Yes +- Type: string + +### Parameter: `replicationSchedule` + +The replication schedule for the volume. + +- Required: Yes +- Type: string + +### Parameter: `snapshotName` + +The name of the snapshot. + +- Required: Yes +- Type: string + +### Parameter: `snapshotPolicyLocation` + +The location of snashot policies. + +- Required: Yes +- Type: string + +### Parameter: `snapshotPolicyName` + +The name of the snapshot policy. + +- Required: Yes +- Type: string + +### Parameter: `subnetResourceId` + +The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. + +- Required: Yes +- Type: string + +### Parameter: `usageThreshold` + +Maximum storage quota allowed for a file system in bytes. + +- Required: Yes +- Type: int + +### Parameter: `useExistingSnapshot` + +Indicates whether to use an existing snapshot. + +- Required: Yes +- Type: bool + +### Parameter: `volumeResourceId` + +The resource ID of the volume. + +- Required: Yes +- Type: string + +### Parameter: `volumeType` + +The type of the volume. DataProtection volumes are used for replication. + +- Required: Yes +- Type: string + +### Parameter: `weeklyBackupsToKeep` + +The weekly backups to keep. + +- Required: Yes +- Type: int + +### Parameter: `weeklyDay` + +The weekly snapshot day. + +- Required: Yes +- Type: string + +### Parameter: `weeklyHour` + +The weekly snapshot hour. + +- Required: Yes +- Type: int + +### Parameter: `weeklyMinute` + +The weekly snapshot minute. + +- Required: Yes +- Type: int + +### Parameter: `weeklySnapshotsToKeep` + +Weekly snapshot count to keep. + +- Required: Yes +- Type: int + +### Parameter: `weeklyUsedBytes` + +Weekly snapshot used bytes. + +- Required: Yes +- Type: int + +### Parameter: `capacityPoolName` + +The name of the parent capacity pool. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `netAppAccountName` + +The name of the parent NetApp account. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `backupEnabled` + +Indicates whether the backup policy is enabled. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `backupPolicyName` + +The name of the backup policy. + +- Required: No +- Type: string +- Default: `'backupPolicy'` + +### Parameter: `backupVaultLocation` + +The location of the backup vault. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `backupVaultName` + +The name of the backup vault. + +- Required: No +- Type: string +- Default: `'vault'` + +### Parameter: `coolAccessRetrievalPolicy` + +determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read). + +- Required: No +- Type: string +- Default: `'Default'` + +### Parameter: `creationToken` + +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. + +- Required: No +- Type: string +- Default: `[parameters('name')]` + +### Parameter: `exportPolicyRules` + +Export policy rules. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `location` + +Location of the pool volume. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + ### Parameter: `networkFeatures` Network feature for the volume. @@ -390,20 +494,6 @@ Set of protocol types. - Type: array - Default: `[]` -### Parameter: `remoteVolumeRegion` - -The remote region for the other end of the Volume Replication. - -- Required: Yes -- Type: string - -### Parameter: `remoteVolumeResourceId` - -The resource ID of the remote volume. - -- Required: Yes -- Type: string - ### Parameter: `replicationEnabled` Boolean to enable replication. @@ -412,13 +502,6 @@ Boolean to enable replication. - Type: bool - Default: `True` -### Parameter: `replicationSchedule` - -The replication schedule for the volume. - -- Required: Yes -- Type: string - ### Parameter: `roleAssignments` Array of role assignments to create. @@ -547,97 +630,6 @@ Indicates whether the snapshot policy is enabled. - Type: bool - Default: `True` -### Parameter: `snapshotName` - -The name of the snapshot. - -- Required: Yes -- Type: string - -### Parameter: `snapshotPolicyId` - -The snapshot Policy id. - -- Required: Yes -- Type: string - -### Parameter: `snapshotPolicyLocation` - -The location of snashot policies. - -- Required: Yes -- Type: string - -### Parameter: `snapshotPolicyName` - -The name of the snapshot policy. - -- Required: Yes -- Type: string - -### Parameter: `useExistingSnapshot` - -Indicates whether to use an existing snapshot. - -- Required: Yes -- Type: bool - -### Parameter: `volumeResourceId` - -The resource ID of the volume. - -- Required: Yes -- Type: string - -### Parameter: `volumeType` - -The type of the volume. DataProtection volumes are used for replication. - -- Required: Yes -- Type: string - -### Parameter: `weeklyBackupsToKeep` - -The weekly backups to keep. - -- Required: Yes -- Type: int - -### Parameter: `weeklyDay` - -The weekly snapshot day. - -- Required: Yes -- Type: string - -### Parameter: `weeklyHour` - -The weekly snapshot hour. - -- Required: Yes -- Type: int - -### Parameter: `weeklyMinute` - -The weekly snapshot minute. - -- Required: Yes -- Type: int - -### Parameter: `weeklySnapshotsToKeep` - -Weekly snapshot count to keep. - -- Required: Yes -- Type: int - -### Parameter: `weeklyUsedBytes` - -Weekly snapshot used bytes. - -- Required: Yes -- Type: int - ### Parameter: `zones` Zone where the volume will be placed. diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep index ce5de13b21..e304428137 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep @@ -8,31 +8,31 @@ param netAppAccountName string @description('Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment.') param capacityPoolName string -@description('Optional. If enabled (true) the pool can contain cool Access enabled volumes.') +@description('Required. If enabled (true) the pool can contain cool Access enabled volumes.') param coolAccess bool -@description('Optional. Specifies the number of days after which data that is not accessed by clients will be tiered.') +@description('Required. Specifies the number of days after which data that is not accessed by clients will be tiered.') param coolnessPeriod int @description('Optional. determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read).') param coolAccessRetrievalPolicy string = 'Default' -@description('Optional. The source of the encryption key.') +@description('Required. The source of the encryption key.') param encryptionKeySource string -@description('Optional. The resource ID of the key vault private endpoint.') +@description('Required. The resource ID of the key vault private endpoint.') param keyVaultPrivateEndpointResourceId string -@description('Optional. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst).') +@description('Required. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst).') param endpointType string -@description('Optional. The remote region for the other end of the Volume Replication.') +@description('Required. The remote region for the other end of the Volume Replication.') param remoteVolumeRegion string -@description('Optional. The resource ID of the remote volume.') +@description('Required. The resource ID of the remote volume.') param remoteVolumeResourceId string -@description('Optional. The replication schedule for the volume.') +@description('Required. The replication schedule for the volume.') param replicationSchedule string @description('Optional. Indicates whether the backup policy is enabled.') @@ -41,70 +41,70 @@ param backupEnabled bool = false @description('Optional. The name of the backup policy.') param backupPolicyName string = 'backupPolicy' -@description('Optional. The daily snapshot hour.') +@description('Required. The daily snapshot hour.') param dailyHour int -@description('Optional. The daily snapshot minute.') +@description('Required. The daily snapshot minute.') param dailyMinute int -@description('Optional. Daily snapshot count to keep.') +@description('Required. Daily snapshot count to keep.') param dailySnapshotsToKeep int -@description('Optional. Daily snapshot used bytes.') +@description('Required. Daily snapshot used bytes.') param dailyUsedBytes int -@description('Optional. The hourly snapshot minute.') +@description('Required. The hourly snapshot minute.') param hourlyMinute int -@description('Optional. Hourly snapshot count to keep.') +@description('Required. Hourly snapshot count to keep.') param hourlySnapshotsToKeep int -@description('Optional. Hourly snapshot used bytes.') +@description('Required. Hourly snapshot used bytes.') param hourlyUsedBytes int -@description('Optional. The monthly snapshot day.') +@description('Required. The monthly snapshot day.') param daysOfMonth string -@description('Optional. The monthly snapshot hour.') +@description('Required. The monthly snapshot hour.') param monthlyHour int -@description('Optional. The monthly snapshot minute.') +@description('Required. The monthly snapshot minute.') param monthlyMinute int -@description('Optional. Monthly snapshot count to keep.') +@description('Required. Monthly snapshot count to keep.') param monthlySnapshotsToKeep int -@description('Optional. Monthly snapshot used bytes.') +@description('Required. Monthly snapshot used bytes.') param monthlyUsedBytes int -@description('Optional. The weekly snapshot day.') +@description('Required. The weekly snapshot day.') param weeklyDay string -@description('Optional. The weekly snapshot hour.') +@description('Required. The weekly snapshot hour.') param weeklyHour int -@description('Optional. The weekly snapshot minute.') +@description('Required. The weekly snapshot minute.') param weeklyMinute int -@description('Optional. Weekly snapshot count to keep.') +@description('Required. Weekly snapshot count to keep.') param weeklySnapshotsToKeep int -@description('Optional. Weekly snapshot used bytes.') +@description('Required. Weekly snapshot used bytes.') param weeklyUsedBytes int @description('Optional. Indicates whether the snapshot policy is enabled.') param snapEnabled bool = true -@description('Optional. The name of the snapshot policy.') +@description('Required. The name of the snapshot policy.') param snapshotPolicyName string -@description('Optional. The daily backups to keep.') +@description('Required. The daily backups to keep.') param dailyBackupsToKeep int -@description('Optional. The monthly backups to keep.') +@description('Required. The monthly backups to keep.') param monthlyBackupsToKeep int -@description('Optional. The weekly backups to keep.') +@description('Required. The weekly backups to keep.') param weeklyBackupsToKeep int @description('Optional. The name of the backup vault.') @@ -113,25 +113,22 @@ param backupVaultName string = 'vault' @description('Optional. The location of the backup vault.') param backupVaultLocation string = resourceGroup().location -@description('Optional. The name of the backup.') +@description('Required. The name of the backup.') param backupName string -@description('Optional. The label of the backup.') +@description('Required. The label of the backup.') param backupLabel string -@description('Optional. Indicates whether to use an existing snapshot.') +@description('Required. Indicates whether to use an existing snapshot.') param useExistingSnapshot bool -@description('Optional. The name of the snapshot.') +@description('Required. The name of the snapshot.') param snapshotName string -@description('Optional. The snapshot Policy id.') -param snapshotPolicyId string - -@description('Optional. The resource ID of the volume.') +@description('Required. The resource ID of the volume.') param volumeResourceId string -@description('Optional. The type of the volume. DataProtection volumes are used for replication.') +@description('Required. The type of the volume. DataProtection volumes are used for replication.') param volumeType string @description('Required. The name of the pool volume.') @@ -146,10 +143,10 @@ param zones array = ['1'] @description('Optional. If Backup policy is enforced.') param policyEnforced bool = false -@description('Optional. The backup policy location.') +@description('Required. The backup policy location.') param backupPolicyLocation string -@description('Optional. The location of snashot policies.') +@description('Required. The location of snashot policies.') param snapshotPolicyLocation string @description('Optional. The pool service level. Must match the one of the parent capacity pool.') @@ -188,7 +185,7 @@ param exportPolicyRules array = [] @description('Optional. Array of role assignments to create.') param roleAssignments roleAssignmentType -@description('Optional. The Id of the Backup Vault.') +@description('Required. The Id of the Backup Vault.') param backupVaultId string @description('Optional. Boolean to enable replication.') diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/main.json b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json index dbbbaa682f..943207bfdd 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/main.json +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "3878108397799577614" + "version": "0.30.23.60470", + "templateHash": "7267638032222261061" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", @@ -103,13 +103,13 @@ "coolAccess": { "type": "bool", "metadata": { - "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + "description": "Required. If enabled (true) the pool can contain cool Access enabled volumes." } }, "coolnessPeriod": { "type": "int", "metadata": { - "description": "Optional. Specifies the number of days after which data that is not accessed by clients will be tiered." + "description": "Required. Specifies the number of days after which data that is not accessed by clients will be tiered." } }, "coolAccessRetrievalPolicy": { @@ -122,37 +122,37 @@ "encryptionKeySource": { "type": "string", "metadata": { - "description": "Optional. The source of the encryption key." + "description": "Required. The source of the encryption key." } }, "keyVaultPrivateEndpointResourceId": { "type": "string", "metadata": { - "description": "Optional. The resource ID of the key vault private endpoint." + "description": "Required. The resource ID of the key vault private endpoint." } }, "endpointType": { "type": "string", "metadata": { - "description": "Optional. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst)." + "description": "Required. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst)." } }, "remoteVolumeRegion": { "type": "string", "metadata": { - "description": "Optional. The remote region for the other end of the Volume Replication." + "description": "Required. The remote region for the other end of the Volume Replication." } }, "remoteVolumeResourceId": { "type": "string", "metadata": { - "description": "Optional. The resource ID of the remote volume." + "description": "Required. The resource ID of the remote volume." } }, "replicationSchedule": { "type": "string", "metadata": { - "description": "Optional. The replication schedule for the volume." + "description": "Required. The replication schedule for the volume." } }, "backupEnabled": { @@ -172,103 +172,103 @@ "dailyHour": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot hour." + "description": "Required. The daily snapshot hour." } }, "dailyMinute": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot minute." + "description": "Required. The daily snapshot minute." } }, "dailySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot count to keep." + "description": "Required. Daily snapshot count to keep." } }, "dailyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot used bytes." + "description": "Required. Daily snapshot used bytes." } }, "hourlyMinute": { "type": "int", "metadata": { - "description": "Optional. The hourly snapshot minute." + "description": "Required. The hourly snapshot minute." } }, "hourlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot count to keep." + "description": "Required. Hourly snapshot count to keep." } }, "hourlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot used bytes." + "description": "Required. Hourly snapshot used bytes." } }, "daysOfMonth": { "type": "string", "metadata": { - "description": "Optional. The monthly snapshot day." + "description": "Required. The monthly snapshot day." } }, "monthlyHour": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot hour." + "description": "Required. The monthly snapshot hour." } }, "monthlyMinute": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot minute." + "description": "Required. The monthly snapshot minute." } }, "monthlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot count to keep." + "description": "Required. Monthly snapshot count to keep." } }, "monthlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot used bytes." + "description": "Required. Monthly snapshot used bytes." } }, "weeklyDay": { "type": "string", "metadata": { - "description": "Optional. The weekly snapshot day." + "description": "Required. The weekly snapshot day." } }, "weeklyHour": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot hour." + "description": "Required. The weekly snapshot hour." } }, "weeklyMinute": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot minute." + "description": "Required. The weekly snapshot minute." } }, "weeklySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot count to keep." + "description": "Required. Weekly snapshot count to keep." } }, "weeklyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot used bytes." + "description": "Required. Weekly snapshot used bytes." } }, "snapEnabled": { @@ -281,25 +281,25 @@ "snapshotPolicyName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot policy." + "description": "Required. The name of the snapshot policy." } }, "dailyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The daily backups to keep." + "description": "Required. The daily backups to keep." } }, "monthlyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The monthly backups to keep." + "description": "Required. The monthly backups to keep." } }, "weeklyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The weekly backups to keep." + "description": "Required. The weekly backups to keep." } }, "backupVaultName": { @@ -319,43 +319,37 @@ "backupName": { "type": "string", "metadata": { - "description": "Optional. The name of the backup." + "description": "Required. The name of the backup." } }, "backupLabel": { "type": "string", "metadata": { - "description": "Optional. The label of the backup." + "description": "Required. The label of the backup." } }, "useExistingSnapshot": { "type": "bool", "metadata": { - "description": "Optional. Indicates whether to use an existing snapshot." + "description": "Required. Indicates whether to use an existing snapshot." } }, "snapshotName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot." - } - }, - "snapshotPolicyId": { - "type": "string", - "metadata": { - "description": "Optional. The snapshot Policy id." + "description": "Required. The name of the snapshot." } }, "volumeResourceId": { "type": "string", "metadata": { - "description": "Optional. The resource ID of the volume." + "description": "Required. The resource ID of the volume." } }, "volumeType": { "type": "string", "metadata": { - "description": "Optional. The type of the volume. DataProtection volumes are used for replication." + "description": "Required. The type of the volume. DataProtection volumes are used for replication." } }, "name": { @@ -390,13 +384,13 @@ "backupPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The backup policy location." + "description": "Required. The backup policy location." } }, "snapshotPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The location of snashot policies." + "description": "Required. The location of snashot policies." } }, "serviceLevel": { @@ -467,7 +461,7 @@ "backupVaultId": { "type": "string", "metadata": { - "description": "Optional. The Id of the Backup Vault." + "description": "Required. The Id of the Backup Vault." } }, "replicationEnabled": { @@ -604,8 +598,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "16399924782439066553" + "version": "0.30.23.60470", + "templateHash": "13036318518380500677" }, "name": "Azure NetApp Files Backup Policy", "description": "This module deploys a Backup Policy for Azure NetApp File.", @@ -622,31 +616,31 @@ "type": "string", "defaultValue": "backupPolicy", "metadata": { - "description": "Required. The name of the backup policy." + "description": "Optional. The name of the backup policy." } }, "backupPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The location of the backup policy. Required if the template is used in a standalone deployment." + "description": "Required. The location of the backup policy. Required if the template is used in a standalone deployment." } }, "dailyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The daily backups to keep." + "description": "Required. The daily backups to keep." } }, "monthlyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The monthly backups to keep." + "description": "Required. The monthly backups to keep." } }, "weeklyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The weekly backups to keep." + "description": "Required. The weekly backups to keep." } }, "backupEnabled": { @@ -775,8 +769,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "17076752505050697613" + "version": "0.30.23.60470", + "templateHash": "12832989826838310090" }, "name": "Azure NetApp Files Snapshot Policy", "description": "This module deploys a Snapshot Policy for an Azure NetApp File.", @@ -792,7 +786,7 @@ "snapshotPolicyName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot policy." + "description": "Required. The name of the snapshot policy." } }, "snapshotPolicyLocation": { @@ -805,103 +799,103 @@ "dailyHour": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot hour." + "description": "Required. The daily snapshot hour." } }, "dailyMinute": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot minute." + "description": "Required. The daily snapshot minute." } }, "dailySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot count to keep." + "description": "Required. Daily snapshot count to keep." } }, "dailyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot used bytes." + "description": "Required. Daily snapshot used bytes." } }, "hourlyMinute": { "type": "int", "metadata": { - "description": "Optional. The hourly snapshot minute." + "description": "Required. The hourly snapshot minute." } }, "hourlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot count to keep." + "description": "Required. Hourly snapshot count to keep." } }, "hourlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot used bytes." + "description": "Required. Hourly snapshot used bytes." } }, "daysOfMonth": { "type": "string", "metadata": { - "description": "Optional. The monthly snapshot day." + "description": "Required. The monthly snapshot day." } }, "monthlyHour": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot hour." + "description": "Required. The monthly snapshot hour." } }, "monthlyMinute": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot minute." + "description": "Required. The monthly snapshot minute." } }, "monthlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot count to keep." + "description": "Required. Monthly snapshot count to keep." } }, "monthlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot used bytes." + "description": "Required. Monthly snapshot used bytes." } }, "weeklyDay": { "type": "string", "metadata": { - "description": "Optional. The weekly snapshot day." + "description": "Required. The weekly snapshot day." } }, "weeklyHour": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot hour." + "description": "Required. The weekly snapshot hour." } }, "weeklyMinute": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot minute." + "description": "Required. The weekly snapshot minute." } }, "weeklySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot count to keep." + "description": "Required. Weekly snapshot count to keep." } }, "weeklyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot used bytes." + "description": "Required. Weekly snapshot used bytes." } }, "snapEnabled": { diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep index d4f0a33392..b6d51f4962 100644 --- a/avm/res/net-app/net-app-account/main.bicep +++ b/avm/res/net-app/net-app-account/main.bicep @@ -124,8 +124,8 @@ var formattedRoleAssignments = [ : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) }) ] -#disable-next-line no-deployments-resources +#disable-next-line no-deployments-resources resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.netapp-netappaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' properties: { @@ -256,7 +256,7 @@ output volumeResourceId string = (capacityPools != []) ? netAppAccount_capacityP type managedIdentitiesType = { @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[] + userAssignedResourceIds: string[]? }? type lockType = { diff --git a/avm/res/net-app/net-app-account/main.json b/avm/res/net-app/net-app-account/main.json index c260cb81ba..6a272ecb4d 100644 --- a/avm/res/net-app/net-app-account/main.json +++ b/avm/res/net-app/net-app-account/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "6577593938028395411" + "version": "0.30.23.60470", + "templateHash": "7902576739801527066" }, "name": "Azure NetApp Files", "description": "This module deploys an Azure NetApp File.", @@ -21,6 +21,7 @@ "items": { "type": "string" }, + "nullable": true, "metadata": { "description": "Optional. The resource ID(s) to assign to the resource." } @@ -503,8 +504,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "5120059204101466005" + "version": "0.30.23.60470", + "templateHash": "1966206032457552782" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -625,13 +626,6 @@ "description": "Optional. The pool service level." } }, - "networkFeatures": { - "type": "string", - "defaultValue": "Standard", - "metadata": { - "description": "Required. Network features available to the volume, or current state of update (Basic/Standard)." - } - }, "size": { "type": "int", "metadata": { @@ -825,9 +819,6 @@ "replicationSchedule": { "value": "[coalesce(tryGet(parameters('volumes')[copyIndex()], 'replicationSchedule'), '')]" }, - "snapshotPolicyId": { - "value": "[coalesce(tryGet(parameters('volumes')[copyIndex()], 'snapshotPolicyId'), '')]" - }, "snapshotPolicyName": { "value": "[coalesce(tryGet(parameters('volumes')[copyIndex()], 'snapshotPolicyName'), 'snapshotPolicy')]" }, @@ -944,8 +935,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "3878108397799577614" + "version": "0.30.23.60470", + "templateHash": "7267638032222261061" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", @@ -1042,13 +1033,13 @@ "coolAccess": { "type": "bool", "metadata": { - "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + "description": "Required. If enabled (true) the pool can contain cool Access enabled volumes." } }, "coolnessPeriod": { "type": "int", "metadata": { - "description": "Optional. Specifies the number of days after which data that is not accessed by clients will be tiered." + "description": "Required. Specifies the number of days after which data that is not accessed by clients will be tiered." } }, "coolAccessRetrievalPolicy": { @@ -1061,37 +1052,37 @@ "encryptionKeySource": { "type": "string", "metadata": { - "description": "Optional. The source of the encryption key." + "description": "Required. The source of the encryption key." } }, "keyVaultPrivateEndpointResourceId": { "type": "string", "metadata": { - "description": "Optional. The resource ID of the key vault private endpoint." + "description": "Required. The resource ID of the key vault private endpoint." } }, "endpointType": { "type": "string", "metadata": { - "description": "Optional. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst)." + "description": "Required. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst)." } }, "remoteVolumeRegion": { "type": "string", "metadata": { - "description": "Optional. The remote region for the other end of the Volume Replication." + "description": "Required. The remote region for the other end of the Volume Replication." } }, "remoteVolumeResourceId": { "type": "string", "metadata": { - "description": "Optional. The resource ID of the remote volume." + "description": "Required. The resource ID of the remote volume." } }, "replicationSchedule": { "type": "string", "metadata": { - "description": "Optional. The replication schedule for the volume." + "description": "Required. The replication schedule for the volume." } }, "backupEnabled": { @@ -1111,103 +1102,103 @@ "dailyHour": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot hour." + "description": "Required. The daily snapshot hour." } }, "dailyMinute": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot minute." + "description": "Required. The daily snapshot minute." } }, "dailySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot count to keep." + "description": "Required. Daily snapshot count to keep." } }, "dailyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot used bytes." + "description": "Required. Daily snapshot used bytes." } }, "hourlyMinute": { "type": "int", "metadata": { - "description": "Optional. The hourly snapshot minute." + "description": "Required. The hourly snapshot minute." } }, "hourlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot count to keep." + "description": "Required. Hourly snapshot count to keep." } }, "hourlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot used bytes." + "description": "Required. Hourly snapshot used bytes." } }, "daysOfMonth": { "type": "string", "metadata": { - "description": "Optional. The monthly snapshot day." + "description": "Required. The monthly snapshot day." } }, "monthlyHour": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot hour." + "description": "Required. The monthly snapshot hour." } }, "monthlyMinute": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot minute." + "description": "Required. The monthly snapshot minute." } }, "monthlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot count to keep." + "description": "Required. Monthly snapshot count to keep." } }, "monthlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot used bytes." + "description": "Required. Monthly snapshot used bytes." } }, "weeklyDay": { "type": "string", "metadata": { - "description": "Optional. The weekly snapshot day." + "description": "Required. The weekly snapshot day." } }, "weeklyHour": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot hour." + "description": "Required. The weekly snapshot hour." } }, "weeklyMinute": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot minute." + "description": "Required. The weekly snapshot minute." } }, "weeklySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot count to keep." + "description": "Required. Weekly snapshot count to keep." } }, "weeklyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot used bytes." + "description": "Required. Weekly snapshot used bytes." } }, "snapEnabled": { @@ -1220,25 +1211,25 @@ "snapshotPolicyName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot policy." + "description": "Required. The name of the snapshot policy." } }, "dailyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The daily backups to keep." + "description": "Required. The daily backups to keep." } }, "monthlyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The monthly backups to keep." + "description": "Required. The monthly backups to keep." } }, "weeklyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The weekly backups to keep." + "description": "Required. The weekly backups to keep." } }, "backupVaultName": { @@ -1258,43 +1249,37 @@ "backupName": { "type": "string", "metadata": { - "description": "Optional. The name of the backup." + "description": "Required. The name of the backup." } }, "backupLabel": { "type": "string", "metadata": { - "description": "Optional. The label of the backup." + "description": "Required. The label of the backup." } }, "useExistingSnapshot": { "type": "bool", "metadata": { - "description": "Optional. Indicates whether to use an existing snapshot." + "description": "Required. Indicates whether to use an existing snapshot." } }, "snapshotName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot." - } - }, - "snapshotPolicyId": { - "type": "string", - "metadata": { - "description": "Optional. The snapshot Policy id." + "description": "Required. The name of the snapshot." } }, "volumeResourceId": { "type": "string", "metadata": { - "description": "Optional. The resource ID of the volume." + "description": "Required. The resource ID of the volume." } }, "volumeType": { "type": "string", "metadata": { - "description": "Optional. The type of the volume. DataProtection volumes are used for replication." + "description": "Required. The type of the volume. DataProtection volumes are used for replication." } }, "name": { @@ -1329,13 +1314,13 @@ "backupPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The backup policy location." + "description": "Required. The backup policy location." } }, "snapshotPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The location of snashot policies." + "description": "Required. The location of snashot policies." } }, "serviceLevel": { @@ -1406,7 +1391,7 @@ "backupVaultId": { "type": "string", "metadata": { - "description": "Optional. The Id of the Backup Vault." + "description": "Required. The Id of the Backup Vault." } }, "replicationEnabled": { @@ -1543,8 +1528,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "16399924782439066553" + "version": "0.30.23.60470", + "templateHash": "13036318518380500677" }, "name": "Azure NetApp Files Backup Policy", "description": "This module deploys a Backup Policy for Azure NetApp File.", @@ -1561,31 +1546,31 @@ "type": "string", "defaultValue": "backupPolicy", "metadata": { - "description": "Required. The name of the backup policy." + "description": "Optional. The name of the backup policy." } }, "backupPolicyLocation": { "type": "string", "metadata": { - "description": "Optional. The location of the backup policy. Required if the template is used in a standalone deployment." + "description": "Required. The location of the backup policy. Required if the template is used in a standalone deployment." } }, "dailyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The daily backups to keep." + "description": "Required. The daily backups to keep." } }, "monthlyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The monthly backups to keep." + "description": "Required. The monthly backups to keep." } }, "weeklyBackupsToKeep": { "type": "int", "metadata": { - "description": "Optional. The weekly backups to keep." + "description": "Required. The weekly backups to keep." } }, "backupEnabled": { @@ -1714,8 +1699,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "17076752505050697613" + "version": "0.30.23.60470", + "templateHash": "12832989826838310090" }, "name": "Azure NetApp Files Snapshot Policy", "description": "This module deploys a Snapshot Policy for an Azure NetApp File.", @@ -1731,7 +1716,7 @@ "snapshotPolicyName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot policy." + "description": "Required. The name of the snapshot policy." } }, "snapshotPolicyLocation": { @@ -1744,103 +1729,103 @@ "dailyHour": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot hour." + "description": "Required. The daily snapshot hour." } }, "dailyMinute": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot minute." + "description": "Required. The daily snapshot minute." } }, "dailySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot count to keep." + "description": "Required. Daily snapshot count to keep." } }, "dailyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot used bytes." + "description": "Required. Daily snapshot used bytes." } }, "hourlyMinute": { "type": "int", "metadata": { - "description": "Optional. The hourly snapshot minute." + "description": "Required. The hourly snapshot minute." } }, "hourlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot count to keep." + "description": "Required. Hourly snapshot count to keep." } }, "hourlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot used bytes." + "description": "Required. Hourly snapshot used bytes." } }, "daysOfMonth": { "type": "string", "metadata": { - "description": "Optional. The monthly snapshot day." + "description": "Required. The monthly snapshot day." } }, "monthlyHour": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot hour." + "description": "Required. The monthly snapshot hour." } }, "monthlyMinute": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot minute." + "description": "Required. The monthly snapshot minute." } }, "monthlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot count to keep." + "description": "Required. Monthly snapshot count to keep." } }, "monthlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot used bytes." + "description": "Required. Monthly snapshot used bytes." } }, "weeklyDay": { "type": "string", "metadata": { - "description": "Optional. The weekly snapshot day." + "description": "Required. The weekly snapshot day." } }, "weeklyHour": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot hour." + "description": "Required. The weekly snapshot hour." } }, "weeklyMinute": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot minute." + "description": "Required. The weekly snapshot minute." } }, "weeklySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot count to keep." + "description": "Required. Weekly snapshot count to keep." } }, "weeklyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot used bytes." + "description": "Required. Weekly snapshot used bytes." } }, "snapEnabled": { diff --git a/avm/res/net-app/net-app-account/snapshot-policies/README.md b/avm/res/net-app/net-app-account/snapshot-policies/README.md index 3fc4b313e2..d059bf9769 100644 --- a/avm/res/net-app/net-app-account/snapshot-policies/README.md +++ b/avm/res/net-app/net-app-account/snapshot-policies/README.md @@ -16,13 +16,7 @@ This module deploys a Snapshot Policy for an Azure NetApp File. ## Parameters -**Conditional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`netAppAccountName`](#parameter-netappaccountname) | string | The name of the parent NetApp account. Required if the template is used in a standalone deployment. | - -**Optional parameters** +**Required parameters** | Parameter | Type | Description | | :-- | :-- | :-- | @@ -38,8 +32,6 @@ This module deploys a Snapshot Policy for an Azure NetApp File. | [`monthlyMinute`](#parameter-monthlyminute) | int | The monthly snapshot minute. | | [`monthlySnapshotsToKeep`](#parameter-monthlysnapshotstokeep) | int | Monthly snapshot count to keep. | | [`monthlyUsedBytes`](#parameter-monthlyusedbytes) | int | Monthly snapshot used bytes. | -| [`snapEnabled`](#parameter-snapenabled) | bool | Indicates whether the snapshot policy is enabled. | -| [`snapshotPolicyLocation`](#parameter-snapshotpolicylocation) | string | The location of the snapshot policy. | | [`snapshotPolicyName`](#parameter-snapshotpolicyname) | string | The name of the snapshot policy. | | [`weeklyDay`](#parameter-weeklyday) | string | The weekly snapshot day. | | [`weeklyHour`](#parameter-weeklyhour) | int | The weekly snapshot hour. | @@ -47,12 +39,18 @@ This module deploys a Snapshot Policy for an Azure NetApp File. | [`weeklySnapshotsToKeep`](#parameter-weeklysnapshotstokeep) | int | Weekly snapshot count to keep. | | [`weeklyUsedBytes`](#parameter-weeklyusedbytes) | int | Weekly snapshot used bytes. | -### Parameter: `netAppAccountName` +**Conditional parameters** -The name of the parent NetApp account. Required if the template is used in a standalone deployment. +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`netAppAccountName`](#parameter-netappaccountname) | string | The name of the parent NetApp account. Required if the template is used in a standalone deployment. | -- Required: Yes -- Type: string +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`snapEnabled`](#parameter-snapenabled) | bool | Indicates whether the snapshot policy is enabled. | +| [`snapshotPolicyLocation`](#parameter-snapshotpolicylocation) | string | The location of the snapshot policy. | ### Parameter: `dailyHour` @@ -138,22 +136,6 @@ Monthly snapshot used bytes. - Required: Yes - Type: int -### Parameter: `snapEnabled` - -Indicates whether the snapshot policy is enabled. - -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `snapshotPolicyLocation` - -The location of the snapshot policy. - -- Required: No -- Type: string -- Default: `[resourceGroup().location]` - ### Parameter: `snapshotPolicyName` The name of the snapshot policy. @@ -196,6 +178,29 @@ Weekly snapshot used bytes. - Required: Yes - Type: int +### Parameter: `netAppAccountName` + +The name of the parent NetApp account. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `snapEnabled` + +Indicates whether the snapshot policy is enabled. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `snapshotPolicyLocation` + +The location of the snapshot policy. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + ## Outputs | Output | Type | Description | diff --git a/avm/res/net-app/net-app-account/snapshot-policies/main.bicep b/avm/res/net-app/net-app-account/snapshot-policies/main.bicep index 66eaca3163..5fc4783aa9 100644 --- a/avm/res/net-app/net-app-account/snapshot-policies/main.bicep +++ b/avm/res/net-app/net-app-account/snapshot-policies/main.bicep @@ -5,61 +5,61 @@ metadata owner = 'Azure/module-maintainers' @description('Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment.') param netAppAccountName string -@description('Optional. The name of the snapshot policy.') +@description('Required. The name of the snapshot policy.') param snapshotPolicyName string @description('Optional. The location of the snapshot policy.') param snapshotPolicyLocation string = resourceGroup().location -@description('Optional. The daily snapshot hour.') +@description('Required. The daily snapshot hour.') param dailyHour int -@description('Optional. The daily snapshot minute.') +@description('Required. The daily snapshot minute.') param dailyMinute int -@description('Optional. Daily snapshot count to keep.') +@description('Required. Daily snapshot count to keep.') param dailySnapshotsToKeep int -@description('Optional. Daily snapshot used bytes.') +@description('Required. Daily snapshot used bytes.') param dailyUsedBytes int -@description('Optional. The hourly snapshot minute.') +@description('Required. The hourly snapshot minute.') param hourlyMinute int -@description('Optional. Hourly snapshot count to keep.') +@description('Required. Hourly snapshot count to keep.') param hourlySnapshotsToKeep int -@description('Optional. Hourly snapshot used bytes.') +@description('Required. Hourly snapshot used bytes.') param hourlyUsedBytes int -@description('Optional. The monthly snapshot day.') +@description('Required. The monthly snapshot day.') param daysOfMonth string -@description('Optional. The monthly snapshot hour.') +@description('Required. The monthly snapshot hour.') param monthlyHour int -@description('Optional. The monthly snapshot minute.') +@description('Required. The monthly snapshot minute.') param monthlyMinute int -@description('Optional. Monthly snapshot count to keep.') +@description('Required. Monthly snapshot count to keep.') param monthlySnapshotsToKeep int -@description('Optional. Monthly snapshot used bytes.') +@description('Required. Monthly snapshot used bytes.') param monthlyUsedBytes int -@description('Optional. The weekly snapshot day.') +@description('Required. The weekly snapshot day.') param weeklyDay string -@description('Optional. The weekly snapshot hour.') +@description('Required. The weekly snapshot hour.') param weeklyHour int -@description('Optional. The weekly snapshot minute.') +@description('Required. The weekly snapshot minute.') param weeklyMinute int -@description('Optional. Weekly snapshot count to keep.') +@description('Required. Weekly snapshot count to keep.') param weeklySnapshotsToKeep int -@description('Optional. Weekly snapshot used bytes.') +@description('Required. Weekly snapshot used bytes.') param weeklyUsedBytes int @description('Optional. Indicates whether the snapshot policy is enabled.') diff --git a/avm/res/net-app/net-app-account/snapshot-policies/main.json b/avm/res/net-app/net-app-account/snapshot-policies/main.json index d92af406dd..b41e85b2cb 100644 --- a/avm/res/net-app/net-app-account/snapshot-policies/main.json +++ b/avm/res/net-app/net-app-account/snapshot-policies/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.3.12046", - "templateHash": "17076752505050697613" + "version": "0.30.23.60470", + "templateHash": "12832989826838310090" }, "name": "Azure NetApp Files Snapshot Policy", "description": "This module deploys a Snapshot Policy for an Azure NetApp File.", @@ -21,7 +21,7 @@ "snapshotPolicyName": { "type": "string", "metadata": { - "description": "Optional. The name of the snapshot policy." + "description": "Required. The name of the snapshot policy." } }, "snapshotPolicyLocation": { @@ -34,103 +34,103 @@ "dailyHour": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot hour." + "description": "Required. The daily snapshot hour." } }, "dailyMinute": { "type": "int", "metadata": { - "description": "Optional. The daily snapshot minute." + "description": "Required. The daily snapshot minute." } }, "dailySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot count to keep." + "description": "Required. Daily snapshot count to keep." } }, "dailyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Daily snapshot used bytes." + "description": "Required. Daily snapshot used bytes." } }, "hourlyMinute": { "type": "int", "metadata": { - "description": "Optional. The hourly snapshot minute." + "description": "Required. The hourly snapshot minute." } }, "hourlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot count to keep." + "description": "Required. Hourly snapshot count to keep." } }, "hourlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Hourly snapshot used bytes." + "description": "Required. Hourly snapshot used bytes." } }, "daysOfMonth": { "type": "string", "metadata": { - "description": "Optional. The monthly snapshot day." + "description": "Required. The monthly snapshot day." } }, "monthlyHour": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot hour." + "description": "Required. The monthly snapshot hour." } }, "monthlyMinute": { "type": "int", "metadata": { - "description": "Optional. The monthly snapshot minute." + "description": "Required. The monthly snapshot minute." } }, "monthlySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot count to keep." + "description": "Required. Monthly snapshot count to keep." } }, "monthlyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Monthly snapshot used bytes." + "description": "Required. Monthly snapshot used bytes." } }, "weeklyDay": { "type": "string", "metadata": { - "description": "Optional. The weekly snapshot day." + "description": "Required. The weekly snapshot day." } }, "weeklyHour": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot hour." + "description": "Required. The weekly snapshot hour." } }, "weeklyMinute": { "type": "int", "metadata": { - "description": "Optional. The weekly snapshot minute." + "description": "Required. The weekly snapshot minute." } }, "weeklySnapshotsToKeep": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot count to keep." + "description": "Required. Weekly snapshot count to keep." } }, "weeklyUsedBytes": { "type": "int", "metadata": { - "description": "Optional. Weekly snapshot used bytes." + "description": "Required. Weekly snapshot used bytes." } }, "snapEnabled": { diff --git a/avm/res/network/application-gateway/README.md b/avm/res/network/application-gateway/README.md index fb363e99f3..89c85ce918 100644 --- a/avm/res/network/application-gateway/README.md +++ b/avm/res/network/application-gateway/README.md @@ -3502,7 +3502,7 @@ The managed identity definition for this resource. The resource ID(s) to assign to the resource. -- Required: Yes +- Required: No - Type: array ### Parameter: `privateEndpoints` @@ -3571,15 +3571,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -3588,6 +3586,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/network/application-gateway/main.bicep b/avm/res/network/application-gateway/main.bicep index ee99759960..ae1a98e018 100644 --- a/avm/res/network/application-gateway/main.bicep +++ b/avm/res/network/application-gateway/main.bicep @@ -483,7 +483,7 @@ output privateEndpoints array = [ type managedIdentitiesType = { @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[] + userAssignedResourceIds: string[]? }? type lockType = { @@ -560,7 +560,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/network/application-gateway/main.json b/avm/res/network/application-gateway/main.json index 9d6559c609..e6246e62f3 100644 --- a/avm/res/network/application-gateway/main.json +++ b/avm/res/network/application-gateway/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17187265964548508241" + "version": "0.30.23.60470", + "templateHash": "8237956651125434199" }, "name": "Network Application Gateways", "description": "This module deploys a Network Application Gateway.", @@ -21,6 +21,7 @@ "items": { "type": "string" }, + "nullable": true, "metadata": { "description": "Optional. The resource ID(s) to assign to the resource." } @@ -228,7 +229,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { diff --git a/avm/res/network/azure-firewall/README.md b/avm/res/network/azure-firewall/README.md index 282958f330..2e71568439 100644 --- a/avm/res/network/azure-firewall/README.md +++ b/avm/res/network/azure-firewall/README.md @@ -18,7 +18,7 @@ This module deploys an Azure Firewall. | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | -| `Microsoft.Network/azureFirewalls` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/azureFirewalls) | +| `Microsoft.Network/azureFirewalls` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/azureFirewalls) | | `Microsoft.Network/publicIPAddresses` | [2023-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-09-01/publicIPAddresses) | ## Usage examples diff --git a/avm/res/network/bastion-host/README.md b/avm/res/network/bastion-host/README.md index 8c95b14dac..d0358319a5 100644 --- a/avm/res/network/bastion-host/README.md +++ b/avm/res/network/bastion-host/README.md @@ -18,7 +18,7 @@ This module deploys a Bastion Host. | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | -| `Microsoft.Network/bastionHosts` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2022-11-01/bastionHosts) | +| `Microsoft.Network/bastionHosts` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/bastionHosts) | | `Microsoft.Network/publicIPAddresses` | [2023-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-09-01/publicIPAddresses) | ## Usage examples @@ -32,7 +32,8 @@ The following section provides usage examples for the module, which were used to - [With a custom public IP address deployed by the module](#example-1-with-a-custom-public-ip-address-deployed-by-the-module) - [Using only defaults](#example-2-using-only-defaults) - [Using large parameter set](#example-3-using-large-parameter-set) -- [WAF-aligned](#example-4-waf-aligned) +- [Private-only deployment](#example-4-private-only-deployment) +- [WAF-aligned](#example-5-waf-aligned) ### Example 1: _With a custom public IP address deployed by the module_ @@ -350,6 +351,11 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { 'hidden-title': 'This is visible in the resource name' Role: 'DeploymentValidation' } + zones: [ + 1 + 2 + 3 + ] } } ``` @@ -442,6 +448,13 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { "hidden-title": "This is visible in the resource name", "Role": "DeploymentValidation" } + }, + "zones": { + "value": [ + 1, + 2, + 3 + ] } } } @@ -506,12 +519,101 @@ param tags = { 'hidden-title': 'This is visible in the resource name' Role: 'DeploymentValidation' } +param zones = [ + 1 + 2 + 3 +] ```

    -### Example 4: _WAF-aligned_ +### Example 4: _Private-only deployment_ + +This instance deploys the module as private-only Bastion deployment. + + +

    + +via Bicep module + +```bicep +module bastionHost 'br/public:avm/res/network/bastion-host:' = { + name: 'bastionHostDeployment' + params: { + // Required parameters + name: 'nbhprv001' + virtualNetworkResourceId: '' + // Non-required parameters + enablePrivateOnlyBastion: true + enableSessionRecording: true + location: '' + skuName: 'Premium' + } +} +``` + +
    +

    + +

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

    + +

    + +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/network/bastion-host:' + +// Required parameters +param name = 'nbhprv001' +param virtualNetworkResourceId = '' +// Non-required parameters +param enablePrivateOnlyBastion = true +param enableSessionRecording = true +param location = '' +param skuName = 'Premium' +``` + +
    +

    + +### Example 5: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. @@ -674,21 +776,24 @@ param tags = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`bastionSubnetPublicIpResourceId`](#parameter-bastionsubnetpublicipresourceid) | string | The Public IP resource ID to associate to the azureBastionSubnet. If empty, then the Public IP that is created as part of this module will be applied to the azureBastionSubnet. | +| [`bastionSubnetPublicIpResourceId`](#parameter-bastionsubnetpublicipresourceid) | string | The Public IP resource ID to associate to the azureBastionSubnet. If empty, then the Public IP that is created as part of this module will be applied to the azureBastionSubnet. This parameter is ignored when enablePrivateOnlyBastion is true. | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | -| [`disableCopyPaste`](#parameter-disablecopypaste) | bool | Choose to disable or enable Copy Paste. | -| [`enableFileCopy`](#parameter-enablefilecopy) | bool | Choose to disable or enable File Copy. | -| [`enableIpConnect`](#parameter-enableipconnect) | bool | Choose to disable or enable IP Connect. | +| [`disableCopyPaste`](#parameter-disablecopypaste) | bool | Choose to disable or enable Copy Paste. For Basic SKU Copy/Paste is always enabled. | +| [`enableFileCopy`](#parameter-enablefilecopy) | bool | Choose to disable or enable File Copy. Not supported for Basic SKU. | +| [`enableIpConnect`](#parameter-enableipconnect) | bool | Choose to disable or enable IP Connect. Not supported for Basic SKU. | | [`enableKerberos`](#parameter-enablekerberos) | bool | Choose to disable or enable Kerberos authentication. | -| [`enableShareableLink`](#parameter-enableshareablelink) | bool | Choose to disable or enable Shareable Link. | +| [`enablePrivateOnlyBastion`](#parameter-enableprivateonlybastion) | bool | Choose to disable or enable Private-only Bastion deployment. The Premium SKU is required for this feature. | +| [`enableSessionRecording`](#parameter-enablesessionrecording) | bool | Choose to disable or enable Session Recording feature. The Premium SKU is required for this feature. If Session Recording is enabled, the Native client support will be disabled. | +| [`enableShareableLink`](#parameter-enableshareablelink) | bool | Choose to disable or enable Shareable Link. Not supported for Basic SKU. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | -| [`publicIPAddressObject`](#parameter-publicipaddressobject) | object | Specifies the properties of the Public IP to create and be used by Azure Bastion, if no existing public IP was provided. | +| [`publicIPAddressObject`](#parameter-publicipaddressobject) | object | Specifies the properties of the Public IP to create and be used by Azure Bastion, if no existing public IP was provided. This parameter is ignored when enablePrivateOnlyBastion is true. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | -| [`scaleUnits`](#parameter-scaleunits) | int | The scale units for the Bastion Host resource. | +| [`scaleUnits`](#parameter-scaleunits) | int | The scale units for the Bastion Host resource. The Basic SKU only supports 2 scale units. | | [`skuName`](#parameter-skuname) | string | The SKU of this Bastion Host. | | [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`zones`](#parameter-zones) | array | A list of availability zones denoting where the Bastion Host resource needs to come from. | ### Parameter: `name` @@ -706,7 +811,7 @@ Shared services Virtual Network resource Id. ### Parameter: `bastionSubnetPublicIpResourceId` -The Public IP resource ID to associate to the azureBastionSubnet. If empty, then the Public IP that is created as part of this module will be applied to the azureBastionSubnet. +The Public IP resource ID to associate to the azureBastionSubnet. If empty, then the Public IP that is created as part of this module will be applied to the azureBastionSubnet. This parameter is ignored when enablePrivateOnlyBastion is true. - Required: No - Type: string @@ -826,7 +931,7 @@ Resource ID of the diagnostic log analytics workspace. For security reasons, it ### Parameter: `disableCopyPaste` -Choose to disable or enable Copy Paste. +Choose to disable or enable Copy Paste. For Basic SKU Copy/Paste is always enabled. - Required: No - Type: bool @@ -834,7 +939,7 @@ Choose to disable or enable Copy Paste. ### Parameter: `enableFileCopy` -Choose to disable or enable File Copy. +Choose to disable or enable File Copy. Not supported for Basic SKU. - Required: No - Type: bool @@ -842,7 +947,7 @@ Choose to disable or enable File Copy. ### Parameter: `enableIpConnect` -Choose to disable or enable IP Connect. +Choose to disable or enable IP Connect. Not supported for Basic SKU. - Required: No - Type: bool @@ -856,9 +961,25 @@ Choose to disable or enable Kerberos authentication. - Type: bool - Default: `False` +### Parameter: `enablePrivateOnlyBastion` + +Choose to disable or enable Private-only Bastion deployment. The Premium SKU is required for this feature. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableSessionRecording` + +Choose to disable or enable Session Recording feature. The Premium SKU is required for this feature. If Session Recording is enabled, the Native client support will be disabled. + +- Required: No +- Type: bool +- Default: `False` + ### Parameter: `enableShareableLink` -Choose to disable or enable Shareable Link. +Choose to disable or enable Shareable Link. Not supported for Basic SKU. - Required: No - Type: bool @@ -918,7 +1039,7 @@ Specify the name of lock. ### Parameter: `publicIPAddressObject` -Specifies the properties of the Public IP to create and be used by Azure Bastion, if no existing public IP was provided. +Specifies the properties of the Public IP to create and be used by Azure Bastion, if no existing public IP was provided. This parameter is ignored when enablePrivateOnlyBastion is true. - Required: No - Type: object @@ -1034,7 +1155,7 @@ The principal type of the assigned principal ID. ### Parameter: `scaleUnits` -The scale units for the Bastion Host resource. +The scale units for the Bastion Host resource. The Basic SKU only supports 2 scale units. - Required: No - Type: int @@ -1051,6 +1172,7 @@ The SKU of this Bastion Host. ```Bicep [ 'Basic' + 'Premium' 'Standard' ] ``` @@ -1062,6 +1184,22 @@ Tags of the resource. - Required: No - Type: object +### Parameter: `zones` + +A list of availability zones denoting where the Bastion Host resource needs to come from. + +- Required: No +- Type: array +- Default: `[]` +- Allowed: + ```Bicep + [ + 1 + 2 + 3 + ] + ``` + ## Outputs | Output | Type | Description | @@ -1078,7 +1216,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/public-ip-address:0.5.1` | Remote reference | +| `br/public:avm/res/network/public-ip-address:0.6.0` | Remote reference | ## Data Collection diff --git a/avm/res/network/bastion-host/main.bicep b/avm/res/network/bastion-host/main.bicep index 3acc37b8df..2e1dd254a3 100644 --- a/avm/res/network/bastion-host/main.bicep +++ b/avm/res/network/bastion-host/main.bicep @@ -11,10 +11,10 @@ param location string = resourceGroup().location @description('Required. Shared services Virtual Network resource Id.') param virtualNetworkResourceId string -@description('Optional. The Public IP resource ID to associate to the azureBastionSubnet. If empty, then the Public IP that is created as part of this module will be applied to the azureBastionSubnet.') +@description('Optional. The Public IP resource ID to associate to the azureBastionSubnet. If empty, then the Public IP that is created as part of this module will be applied to the azureBastionSubnet. This parameter is ignored when enablePrivateOnlyBastion is true.') param bastionSubnetPublicIpResourceId string = '' -@description('Optional. Specifies the properties of the Public IP to create and be used by Azure Bastion, if no existing public IP was provided.') +@description('Optional. Specifies the properties of the Public IP to create and be used by Azure Bastion, if no existing public IP was provided. This parameter is ignored when enablePrivateOnlyBastion is true.') param publicIPAddressObject object = { name: '${name}-pip' } @@ -27,27 +27,34 @@ param lock lockType @allowed([ 'Basic' + 'Premium' 'Standard' ]) @description('Optional. The SKU of this Bastion Host.') param skuName string = 'Basic' -@description('Optional. Choose to disable or enable Copy Paste.') +@description('Optional. Choose to disable or enable Copy Paste. For Basic SKU Copy/Paste is always enabled.') param disableCopyPaste bool = false -@description('Optional. Choose to disable or enable File Copy.') +@description('Optional. Choose to disable or enable File Copy. Not supported for Basic SKU.') param enableFileCopy bool = true -@description('Optional. Choose to disable or enable IP Connect.') +@description('Optional. Choose to disable or enable IP Connect. Not supported for Basic SKU.') param enableIpConnect bool = false @description('Optional. Choose to disable or enable Kerberos authentication.') param enableKerberos bool = false -@description('Optional. Choose to disable or enable Shareable Link.') +@description('Optional. Choose to disable or enable Shareable Link. Not supported for Basic SKU.') param enableShareableLink bool = false -@description('Optional. The scale units for the Bastion Host resource.') +@description('Optional. Choose to disable or enable Session Recording feature. The Premium SKU is required for this feature. If Session Recording is enabled, the Native client support will be disabled.') +param enableSessionRecording bool = false + +@description('Optional. Choose to disable or enable Private-only Bastion deployment. The Premium SKU is required for this feature.') +param enablePrivateOnlyBastion bool = false + +@description('Optional. The scale units for the Bastion Host resource. The Basic SKU only supports 2 scale units.') param scaleUnits int = 2 @description('Optional. Array of role assignments to create.') @@ -59,6 +66,14 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true +@description('Optional. A list of availability zones denoting where the Bastion Host resource needs to come from.') +@allowed([ + 1 + 2 + 3 +]) +param zones int[] = [] // Availability Zones are currently in preview and only available in certain regions, therefore the default is an empty array. + // ---------------------------------------------------------------------------- // Prep ipConfigurations object AzureBastionSubnet for different uses cases: // 1. Use existing Public IP @@ -72,14 +87,16 @@ var ipConfigurations = [ id: '${virtualNetworkResourceId}/subnets/AzureBastionSubnet' // The subnet name must be AzureBastionSubnet } }, - { - //Use existing Public IP, new Public IP created in this module - publicIPAddress: { - id: !empty(bastionSubnetPublicIpResourceId) - ? bastionSubnetPublicIpResourceId - : publicIPAddress.outputs.resourceId - } - } + (!enablePrivateOnlyBastion + ? { + //Use existing Public IP, new Public IP created in this module + publicIPAddress: { + id: !empty(bastionSubnetPublicIpResourceId) + ? bastionSubnetPublicIpResourceId + : publicIPAddress.outputs.resourceId + } + } + : {}) ) } ] @@ -130,7 +147,7 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableT } } -module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.5.1' = if (empty(bastionSubnetPublicIpResourceId)) { +module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.6.0' = if (empty(bastionSubnetPublicIpResourceId) && (!enablePrivateOnlyBastion)) { name: '${uniqueString(deployment().name, location)}-Bastion-PIP' params: { name: publicIPAddressObject.name @@ -145,7 +162,7 @@ module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.5.1' = if skuName: publicIPAddressObject.?skuName skuTier: publicIPAddressObject.?skuTier tags: publicIPAddressObject.?tags ?? tags - zones: publicIPAddressObject.?zones + zones: publicIPAddressObject.?zones ?? (length(zones) > 0 ? zones : null) // if zones of the Public IP is empty, use the zones from the bastion host only if not empty (if empty, the default of the public IP will be used) } } @@ -153,26 +170,37 @@ var bastionpropertiesVar = union( { scaleUnits: skuName == 'Basic' ? 2 : scaleUnits ipConfigurations: ipConfigurations - enableKerberos: enableKerberos }, - (skuName == 'Standard' + ((skuName == 'Basic' || skuName == 'Standard' || skuName == 'Premium') + ? { + enableKerberos: enableKerberos + } + : {}), + ((skuName == 'Standard' || skuName == 'Premium') ? { - enableTunneling: skuName == 'Standard' + enableTunneling: skuName == 'Standard' ? true : (enableSessionRecording ? false : true) // Tunneling is enabled by default for Standard SKU. For Premium SKU it is disabled by default if Session Recording is enabled. disableCopyPaste: disableCopyPaste enableFileCopy: enableFileCopy enableIpConnect: enableIpConnect enableShareableLink: enableShareableLink } + : {}), + (skuName == 'Premium' + ? { + enableSessionRecording: enableSessionRecording + enablePrivateOnlyBastion: enablePrivateOnlyBastion + } : {}) ) -resource azureBastion 'Microsoft.Network/bastionHosts@2022-11-01' = { +resource azureBastion 'Microsoft.Network/bastionHosts@2024-01-01' = { name: name location: location tags: tags sku: { name: skuName } + zones: map(zones, zone => string(zone)) properties: bastionpropertiesVar } diff --git a/avm/res/network/bastion-host/main.json b/avm/res/network/bastion-host/main.json index 2634dae54b..a66baf992b 100644 --- a/avm/res/network/bastion-host/main.json +++ b/avm/res/network/bastion-host/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17557675644366875046" + "version": "0.30.23.60470", + "templateHash": "1273376840607599272" }, "name": "Bastion Hosts", "description": "This module deploys a Bastion Host.", @@ -231,7 +231,7 @@ "type": "string", "defaultValue": "", "metadata": { - "description": "Optional. The Public IP resource ID to associate to the azureBastionSubnet. If empty, then the Public IP that is created as part of this module will be applied to the azureBastionSubnet." + "description": "Optional. The Public IP resource ID to associate to the azureBastionSubnet. If empty, then the Public IP that is created as part of this module will be applied to the azureBastionSubnet. This parameter is ignored when enablePrivateOnlyBastion is true." } }, "publicIPAddressObject": { @@ -240,7 +240,7 @@ "name": "[format('{0}-pip', parameters('name'))]" }, "metadata": { - "description": "Optional. Specifies the properties of the Public IP to create and be used by Azure Bastion, if no existing public IP was provided." + "description": "Optional. Specifies the properties of the Public IP to create and be used by Azure Bastion, if no existing public IP was provided. This parameter is ignored when enablePrivateOnlyBastion is true." } }, "diagnosticSettings": { @@ -260,6 +260,7 @@ "defaultValue": "Basic", "allowedValues": [ "Basic", + "Premium", "Standard" ], "metadata": { @@ -270,21 +271,21 @@ "type": "bool", "defaultValue": false, "metadata": { - "description": "Optional. Choose to disable or enable Copy Paste." + "description": "Optional. Choose to disable or enable Copy Paste. For Basic SKU Copy/Paste is always enabled." } }, "enableFileCopy": { "type": "bool", "defaultValue": true, "metadata": { - "description": "Optional. Choose to disable or enable File Copy." + "description": "Optional. Choose to disable or enable File Copy. Not supported for Basic SKU." } }, "enableIpConnect": { "type": "bool", "defaultValue": false, "metadata": { - "description": "Optional. Choose to disable or enable IP Connect." + "description": "Optional. Choose to disable or enable IP Connect. Not supported for Basic SKU." } }, "enableKerberos": { @@ -298,14 +299,28 @@ "type": "bool", "defaultValue": false, "metadata": { - "description": "Optional. Choose to disable or enable Shareable Link." + "description": "Optional. Choose to disable or enable Shareable Link. Not supported for Basic SKU." + } + }, + "enableSessionRecording": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Choose to disable or enable Session Recording feature. The Premium SKU is required for this feature. If Session Recording is enabled, the Native client support will be disabled." + } + }, + "enablePrivateOnlyBastion": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Choose to disable or enable Private-only Bastion deployment. The Premium SKU is required for this feature." } }, "scaleUnits": { "type": "int", "defaultValue": 2, "metadata": { - "description": "Optional. The scale units for the Bastion Host resource." + "description": "Optional. The scale units for the Bastion Host resource. The Basic SKU only supports 2 scale units." } }, "roleAssignments": { @@ -327,6 +342,21 @@ "metadata": { "description": "Optional. Enable/Disable usage telemetry for module." } + }, + "zones": { + "type": "array", + "items": { + "type": "int" + }, + "defaultValue": [], + "allowedValues": [ + 1, + 2, + 3 + ], + "metadata": { + "description": "Optional. A list of availability zones denoting where the Bastion Host resource needs to come from." + } } }, "variables": { @@ -368,14 +398,15 @@ }, "azureBastion": { "type": "Microsoft.Network/bastionHosts", - "apiVersion": "2022-11-01", + "apiVersion": "2024-01-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", "sku": { "name": "[parameters('skuName')]" }, - "properties": "[union(createObject('scaleUnits', if(equals(parameters('skuName'), 'Basic'), 2, parameters('scaleUnits')), 'ipConfigurations', createArray(createObject('name', 'IpConfAzureBastionSubnet', 'properties', union(createObject('subnet', createObject('id', format('{0}/subnets/AzureBastionSubnet', parameters('virtualNetworkResourceId')))), createObject('publicIPAddress', createObject('id', if(not(empty(parameters('bastionSubnetPublicIpResourceId'))), parameters('bastionSubnetPublicIpResourceId'), reference('publicIPAddress').outputs.resourceId.value)))))), 'enableKerberos', parameters('enableKerberos')), if(equals(parameters('skuName'), 'Standard'), createObject('enableTunneling', equals(parameters('skuName'), 'Standard'), 'disableCopyPaste', parameters('disableCopyPaste'), 'enableFileCopy', parameters('enableFileCopy'), 'enableIpConnect', parameters('enableIpConnect'), 'enableShareableLink', parameters('enableShareableLink')), createObject()))]", + "zones": "[map(parameters('zones'), lambda('zone', string(lambdaVariables('zone'))))]", + "properties": "[union(createObject('scaleUnits', if(equals(parameters('skuName'), 'Basic'), 2, parameters('scaleUnits')), 'ipConfigurations', createArray(createObject('name', 'IpConfAzureBastionSubnet', 'properties', union(createObject('subnet', createObject('id', format('{0}/subnets/AzureBastionSubnet', parameters('virtualNetworkResourceId')))), if(not(parameters('enablePrivateOnlyBastion')), createObject('publicIPAddress', createObject('id', if(not(empty(parameters('bastionSubnetPublicIpResourceId'))), parameters('bastionSubnetPublicIpResourceId'), reference('publicIPAddress').outputs.resourceId.value))), createObject()))))), if(or(or(equals(parameters('skuName'), 'Basic'), equals(parameters('skuName'), 'Standard')), equals(parameters('skuName'), 'Premium')), createObject('enableKerberos', parameters('enableKerberos')), createObject()), if(or(equals(parameters('skuName'), 'Standard'), equals(parameters('skuName'), 'Premium')), createObject('enableTunneling', if(equals(parameters('skuName'), 'Standard'), true(), if(parameters('enableSessionRecording'), false(), true())), 'disableCopyPaste', parameters('disableCopyPaste'), 'enableFileCopy', parameters('enableFileCopy'), 'enableIpConnect', parameters('enableIpConnect'), 'enableShareableLink', parameters('enableShareableLink')), createObject()), if(equals(parameters('skuName'), 'Premium'), createObject('enableSessionRecording', parameters('enableSessionRecording'), 'enablePrivateOnlyBastion', parameters('enablePrivateOnlyBastion')), createObject()))]", "dependsOn": [ "publicIPAddress" ] @@ -449,7 +480,7 @@ ] }, "publicIPAddress": { - "condition": "[empty(parameters('bastionSubnetPublicIpResourceId'))]", + "condition": "[and(empty(parameters('bastionSubnetPublicIpResourceId')), not(parameters('enablePrivateOnlyBastion')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-Bastion-PIP', uniqueString(deployment().name, parameters('location')))]", @@ -496,7 +527,7 @@ "value": "[coalesce(tryGet(parameters('publicIPAddressObject'), 'tags'), parameters('tags'))]" }, "zones": { - "value": "[tryGet(parameters('publicIPAddressObject'), 'zones')]" + "value": "[coalesce(tryGet(parameters('publicIPAddressObject'), 'zones'), if(greater(length(parameters('zones')), 0), parameters('zones'), null()))]" } }, "template": { @@ -507,7 +538,7 @@ "_generator": { "name": "bicep", "version": "0.29.47.4906", - "templateHash": "14450344965065009842" + "templateHash": "16693645977675862540" }, "name": "Public IP Addresses", "description": "This module deploys a Public IP Address.", @@ -956,7 +987,7 @@ "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" } }, "resources": { @@ -964,7 +995,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.5.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.6.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1147,7 +1178,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('azureBastion', '2022-11-01', 'full').location]" + "value": "[reference('azureBastion', '2024-01-01', 'full').location]" }, "ipConfAzureBastionSubnet": { "type": "object", diff --git a/avm/res/network/bastion-host/tests/e2e/custompip/dependencies.bicep b/avm/res/network/bastion-host/tests/e2e/custompip/dependencies.bicep index efadbb5134..4166c9be72 100644 --- a/avm/res/network/bastion-host/tests/e2e/custompip/dependencies.bicep +++ b/avm/res/network/bastion-host/tests/e2e/custompip/dependencies.bicep @@ -9,7 +9,7 @@ param managedIdentityName string var addressPrefix = '10.0.0.0/16' -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-01-01' = { name: virtualNetworkName location: location properties: { diff --git a/avm/res/network/bastion-host/tests/e2e/custompip/main.test.bicep b/avm/res/network/bastion-host/tests/e2e/custompip/main.test.bicep index a72e08b814..c2cc1046b8 100644 --- a/avm/res/network/bastion-host/tests/e2e/custompip/main.test.bicep +++ b/avm/res/network/bastion-host/tests/e2e/custompip/main.test.bicep @@ -26,7 +26,7 @@ param namePrefix string = '#_namePrefix_#' // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName location: resourceLocation } diff --git a/avm/res/network/bastion-host/tests/e2e/defaults/dependencies.bicep b/avm/res/network/bastion-host/tests/e2e/defaults/dependencies.bicep index 40255471c0..7aada15d55 100644 --- a/avm/res/network/bastion-host/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/network/bastion-host/tests/e2e/defaults/dependencies.bicep @@ -6,7 +6,7 @@ param virtualNetworkName string var addressPrefix = '10.0.0.0/16' -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-01-01' = { name: virtualNetworkName location: location properties: { diff --git a/avm/res/network/bastion-host/tests/e2e/defaults/main.test.bicep b/avm/res/network/bastion-host/tests/e2e/defaults/main.test.bicep index f103fca5f0..19706f01fd 100644 --- a/avm/res/network/bastion-host/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/bastion-host/tests/e2e/defaults/main.test.bicep @@ -26,7 +26,7 @@ param namePrefix string = '#_namePrefix_#' // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName location: resourceLocation } diff --git a/avm/res/network/bastion-host/tests/e2e/max/dependencies.bicep b/avm/res/network/bastion-host/tests/e2e/max/dependencies.bicep index c25af5e3e7..1ff59b7834 100644 --- a/avm/res/network/bastion-host/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/bastion-host/tests/e2e/max/dependencies.bicep @@ -12,7 +12,7 @@ param managedIdentityName string var addressPrefix = '10.0.0.0/16' -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-01-01' = { name: virtualNetworkName location: location properties: { @@ -32,13 +32,18 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } } -resource publicIP 'Microsoft.Network/publicIPAddresses@2023-04-01' = { +resource publicIP 'Microsoft.Network/publicIPAddresses@2024-01-01' = { name: publicIPName location: location sku: { name: 'Standard' tier: 'Regional' } + zones: [ + '1' + '2' + '3' + ] properties: { publicIPAllocationMethod: 'Static' } diff --git a/avm/res/network/bastion-host/tests/e2e/max/main.test.bicep b/avm/res/network/bastion-host/tests/e2e/max/main.test.bicep index 9fe5b24a03..2c3bca2a20 100644 --- a/avm/res/network/bastion-host/tests/e2e/max/main.test.bicep +++ b/avm/res/network/bastion-host/tests/e2e/max/main.test.bicep @@ -11,34 +11,35 @@ metadata description = 'This instance deploys the module with most of its featur @maxLength(90) param resourceGroupName string = 'dep-${namePrefix}-network.bastionhosts-${serviceShort}-rg' -@description('Optional. The location to deploy resources to.') -param resourceLocation string = deployment().location - @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') param serviceShort string = 'nbhmax' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' +// Availability zones are currently in preview and not available in all regions. This region must be used in the AVM testing subscription +#disable-next-line no-hardcoded-location +var enforcedLocation = 'northeurope' + // ============ // // Dependencies // // ============ // // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName - location: resourceLocation + location: enforcedLocation } module nestedDependencies 'dependencies.bicep' = { scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' params: { virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' publicIPName: 'dep-${namePrefix}-pip-${serviceShort}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - location: resourceLocation + location: enforcedLocation } } @@ -46,13 +47,13 @@ module nestedDependencies 'dependencies.bicep' = { // =========== module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + name: '${uniqueString(deployment().name, enforcedLocation)}-diagnosticDependencies' params: { storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' - location: resourceLocation + location: enforcedLocation } } @@ -64,10 +65,10 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t module testDeployment '../../../main.bicep' = [ for iteration in ['init', 'idem']: { scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: resourceLocation + location: enforcedLocation virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId bastionSubnetPublicIpResourceId: nestedDependencies.outputs.publicIPResourceId diagnosticSettings: [ @@ -116,6 +117,11 @@ module testDeployment '../../../main.bicep' = [ Environment: 'Non-Prod' Role: 'DeploymentValidation' } + zones: [ + 1 + 2 + 3 + ] } dependsOn: [ nestedDependencies diff --git a/avm/res/network/bastion-host/tests/e2e/private/dependencies.bicep b/avm/res/network/bastion-host/tests/e2e/private/dependencies.bicep new file mode 100644 index 0000000000..7aada15d55 --- /dev/null +++ b/avm/res/network/bastion-host/tests/e2e/private/dependencies.bicep @@ -0,0 +1,30 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-01-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'AzureBastionSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = virtualNetwork.id diff --git a/avm/res/network/bastion-host/tests/e2e/private/main.test.bicep b/avm/res/network/bastion-host/tests/e2e/private/main.test.bicep new file mode 100644 index 0000000000..b35c9f07a9 --- /dev/null +++ b/avm/res/network/bastion-host/tests/e2e/private/main.test.bicep @@ -0,0 +1,61 @@ +targetScope = 'subscription' + +metadata name = 'Private-only deployment' +metadata description = 'This instance deploys the module as private-only Bastion deployment.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.bastionhosts-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nbhprv' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + skuName: 'Premium' + enableSessionRecording: true + enablePrivateOnlyBastion: true + } + } +] diff --git a/avm/res/network/bastion-host/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/bastion-host/tests/e2e/waf-aligned/dependencies.bicep index 32fbd648ed..8027783d25 100644 --- a/avm/res/network/bastion-host/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/network/bastion-host/tests/e2e/waf-aligned/dependencies.bicep @@ -9,7 +9,7 @@ param publicIPName string var addressPrefix = '10.0.0.0/16' -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-01-01' = { name: virtualNetworkName location: location properties: { @@ -39,6 +39,11 @@ resource publicIP 'Microsoft.Network/publicIPAddresses@2023-04-01' = { properties: { publicIPAllocationMethod: 'Static' } + zones: [ + '1' + '2' + '3' + ] } @description('The resource ID of the created Virtual Network.') diff --git a/avm/res/network/bastion-host/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/bastion-host/tests/e2e/waf-aligned/main.test.bicep index 6fb0ed60a0..08ee448bf7 100644 --- a/avm/res/network/bastion-host/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/bastion-host/tests/e2e/waf-aligned/main.test.bicep @@ -26,7 +26,7 @@ param namePrefix string = '#_namePrefix_#' // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName location: resourceLocation } diff --git a/avm/res/network/bastion-host/version.json b/avm/res/network/bastion-host/version.json index 3f863a2bec..ea4f3b6e67 100644 --- a/avm/res/network/bastion-host/version.json +++ b/avm/res/network/bastion-host/version.json @@ -1,7 +1,7 @@ { - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", - "pathFilters": [ - "./main.json" - ] + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.5", + "pathFilters": [ + "./main.json" + ] } \ No newline at end of file diff --git a/avm/res/network/firewall-policy/README.md b/avm/res/network/firewall-policy/README.md index 067f1a3fe5..304e1f9755 100644 --- a/avm/res/network/firewall-policy/README.md +++ b/avm/res/network/firewall-policy/README.md @@ -14,6 +14,8 @@ This module deploys a Firewall Policy. | Resource Type | API Version | | :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Network/firewallPolicies` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/firewallPolicies) | | `Microsoft.Network/firewallPolicies/ruleCollectionGroups` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/firewallPolicies/ruleCollectionGroups) | @@ -112,12 +114,35 @@ module firewallPolicy 'br/public:avm/res/network/firewall-policy:' = { allowSqlRedirect: true autoLearnPrivateRanges: 'Enabled' location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } managedIdentities: { userAssignedResourceIds: [ '' ] } mode: 'Alert' + roleAssignments: [ + { + name: 'c1c7fa14-5a90-4932-8781-fa91318b8858' + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + name: '' + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] ruleCollectionGroups: [ { name: 'rule-001' @@ -192,6 +217,12 @@ module firewallPolicy 'br/public:avm/res/network/firewall-policy:' = { "location": { "value": "" }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, "managedIdentities": { "value": { "userAssignedResourceIds": [ @@ -202,6 +233,27 @@ module firewallPolicy 'br/public:avm/res/network/firewall-policy:' = { "mode": { "value": "Alert" }, + "roleAssignments": { + "value": [ + { + "name": "c1c7fa14-5a90-4932-8781-fa91318b8858", + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "name": "", + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, "ruleCollectionGroups": { "value": [ { @@ -272,12 +324,35 @@ param name = 'nfpmax001' param allowSqlRedirect = true param autoLearnPrivateRanges = 'Enabled' param location = '' +param lock = { + kind: 'CanNotDelete' + name: 'myCustomLockName' +} param managedIdentities = { userAssignedResourceIds: [ '' ] } param mode = 'Alert' +param roleAssignments = [ + { + name: 'c1c7fa14-5a90-4932-8781-fa91318b8858' + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + name: '' + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } +] param ruleCollectionGroups = [ { name: 'rule-001' @@ -564,10 +639,12 @@ param threatIntelMode = 'Deny' | [`ipAddresses`](#parameter-ipaddresses) | array | List of IP addresses for the ThreatIntel Allowlist. | | [`keyVaultSecretId`](#parameter-keyvaultsecretid) | string | Secret ID of (base-64 encoded unencrypted PFX) Secret or Certificate object stored in KeyVault. | | [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | | [`mode`](#parameter-mode) | string | The configuring of intrusion detection. | | [`privateRanges`](#parameter-privateranges) | array | List of private IP addresses/IP address ranges to not be SNAT. | | [`retentionDays`](#parameter-retentiondays) | int | Number of days the insights should be enabled on the policy. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | | [`ruleCollectionGroups`](#parameter-rulecollectiongroups) | array | Rule collection groups. | | [`servers`](#parameter-servers) | array | List of Custom DNS Servers. | | [`signatureOverrides`](#parameter-signatureoverrides) | array | List of specific signatures states. | @@ -687,6 +764,42 @@ Location for all resources. - Type: string - Default: `[resourceGroup().location]` +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + ### Parameter: `managedIdentities` The managed identity definition for this resource. @@ -739,6 +852,109 @@ Number of days the insights should be enabled on the policy. - Type: int - Default: `365` +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array +- Roles configurable by name: + - `'Contributor'` + - `'Owner'` + - `'Reader'` + - `'Role Based Access Control Administrator'` + - `'User Access Administrator'` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`name`](#parameter-roleassignmentsname) | string | The name (as GUID) of the role assignment. If not provided, a GUID will be generated. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.name` + +The name (as GUID) of the role assignment. If not provided, a GUID will be generated. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + ### Parameter: `ruleCollectionGroups` Rule collection groups. diff --git a/avm/res/network/firewall-policy/main.bicep b/avm/res/network/firewall-policy/main.bicep index 1c19610753..3b531e2387 100644 --- a/avm/res/network/firewall-policy/main.bicep +++ b/avm/res/network/firewall-policy/main.bicep @@ -97,6 +97,12 @@ param enableTelemetry bool = true @description('Optional. Rule collection groups.') param ruleCollectionGroups array? +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + var formattedUserAssignedIdentities = reduce( map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, @@ -110,6 +116,31 @@ var identity = !empty(managedIdentities) } : null +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) +} + +var formattedRoleAssignments = [ + for (roleAssignment, index) in (roleAssignments ?? []): union(roleAssignment, { + roleDefinitionId: builtInRoleNames[?roleAssignment.roleDefinitionIdOrName] ?? (contains( + roleAssignment.roleDefinitionIdOrName, + '/providers/Microsoft.Authorization/roleDefinitions/' + ) + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) + }) +] + #disable-next-line no-deployments-resources resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { name: '46d3xbcp.res.network-firewallpolicy.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' @@ -212,6 +243,33 @@ module firewallPolicy_ruleCollectionGroups 'rule-collection-group/main.bicep' = } ] +resource firewallPolicy_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (formattedRoleAssignments ?? []): { + name: roleAssignment.?name ?? guid(firewallPolicy.id, roleAssignment.principalId, roleAssignment.roleDefinitionId) + properties: { + roleDefinitionId: roleAssignment.roleDefinitionId + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: firewallPolicy + } +] + +resource firewallPolicy_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' + ? 'Cannot delete resource or child resources.' + : 'Cannot delete or modify the resource or child resources.' + } + scope: firewallPolicy +} + @description('The name of the deployed firewall policy.') output name string = firewallPolicy.name @@ -232,3 +290,37 @@ type managedIdentitiesType = { @description('Optional. The resource ID(s) to assign to the resource.') userAssignedResourceIds: string[] }? + +type roleAssignmentType = { + @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') + name: string? + + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? diff --git a/avm/res/network/firewall-policy/main.json b/avm/res/network/firewall-policy/main.json index c480fd3ed6..299b7947a5 100644 --- a/avm/res/network/firewall-policy/main.json +++ b/avm/res/network/firewall-policy/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "8226719913431972406" + "version": "0.30.23.60470", + "templateHash": "15412546608723758936" }, "name": "Firewall Policies", "description": "This module deploys a Firewall Policy.", @@ -27,6 +27,104 @@ } }, "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true } }, "parameters": { @@ -221,11 +319,37 @@ "metadata": { "description": "Optional. Rule collection groups." } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", - "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', 'UserAssigned', 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]" + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', 'UserAssigned', 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } }, "resources": { "avmTelemetry": { @@ -275,6 +399,42 @@ "transportSecurity": "[if(or(not(empty(coalesce(parameters('keyVaultSecretId'), createArray()))), not(empty(coalesce(parameters('certificateName'), '')))), createObject('certificateAuthority', createObject('keyVaultSecretId', parameters('keyVaultSecretId'), 'name', parameters('certificateName'))), null())]" } }, + "firewallPolicy_roleAssignments": { + "copy": { + "name": "firewallPolicy_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/firewallPolicies/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/firewallPolicies', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "firewallPolicy" + ] + }, + "firewallPolicy_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/firewallPolicies/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "firewallPolicy" + ] + }, "firewallPolicy_ruleCollectionGroups": { "copy": { "name": "firewallPolicy_ruleCollectionGroups", @@ -311,8 +471,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "3312659149635915423" + "version": "0.30.23.60470", + "templateHash": "4286918441341976962" }, "name": "Firewall Policy Rule Collection Groups", "description": "This module deploys a Firewall Policy Rule Collection Group.", diff --git a/avm/res/network/firewall-policy/rule-collection-group/main.json b/avm/res/network/firewall-policy/rule-collection-group/main.json index 8fd8a36653..c3276a62ed 100644 --- a/avm/res/network/firewall-policy/rule-collection-group/main.json +++ b/avm/res/network/firewall-policy/rule-collection-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "15656278354863511578" + "version": "0.30.23.60470", + "templateHash": "4286918441341976962" }, "name": "Firewall Policy Rule Collection Groups", "description": "This module deploys a Firewall Policy Rule Collection Group.", diff --git a/avm/res/network/firewall-policy/tests/e2e/max/dependencies.bicep b/avm/res/network/firewall-policy/tests/e2e/max/dependencies.bicep index 4fa0028b8a..544accb4a5 100644 --- a/avm/res/network/firewall-policy/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/firewall-policy/tests/e2e/max/dependencies.bicep @@ -11,3 +11,6 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- @description('The resource ID of the created Managed Identity.') output managedIdentityResourceId string = managedIdentity.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/network/firewall-policy/tests/e2e/max/main.test.bicep b/avm/res/network/firewall-policy/tests/e2e/max/main.test.bicep index b713f73fbf..d84b91d977 100644 --- a/avm/res/network/firewall-policy/tests/e2e/max/main.test.bicep +++ b/avm/res/network/firewall-policy/tests/e2e/max/main.test.bicep @@ -97,6 +97,32 @@ module testDeployment '../../../main.bicep' = [ nestedDependencies.outputs.managedIdentityResourceId ] } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + name: 'c1c7fa14-5a90-4932-8781-fa91318b8858' + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + name: guid('Custom seed ${namePrefix}${serviceShort}') + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] tags: { 'hidden-title': 'This is visible in the resource name' Environment: 'Non-Prod' diff --git a/avm/res/network/firewall-policy/version.json b/avm/res/network/firewall-policy/version.json index 83083db694..729ac87673 100644 --- a/avm/res/network/firewall-policy/version.json +++ b/avm/res/network/firewall-policy/version.json @@ -1,7 +1,7 @@ { - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", - "pathFilters": [ - "./main.json" - ] + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.2", + "pathFilters": [ + "./main.json" + ] } \ No newline at end of file diff --git a/avm/res/network/front-door-web-application-firewall-policy/README.md b/avm/res/network/front-door-web-application-firewall-policy/README.md index 830c52b31e..45bfcccf86 100644 --- a/avm/res/network/front-door-web-application-firewall-policy/README.md +++ b/avm/res/network/front-door-web-application-firewall-policy/README.md @@ -16,7 +16,7 @@ This module deploys a Front Door Web Application Firewall (WAF) Policy. | :-- | :-- | | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | -| `Microsoft.Network/FrontDoorWebApplicationFirewallPolicies` | [2024-02-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/FrontDoorWebApplicationFirewallPolicies) | +| `Microsoft.Network/FrontDoorWebApplicationFirewallPolicies` | [2024-02-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-02-01/FrontDoorWebApplicationFirewallPolicies) | ## Usage examples diff --git a/avm/res/network/private-endpoint/README.md b/avm/res/network/private-endpoint/README.md index 3db54f7e96..73417838cc 100644 --- a/avm/res/network/private-endpoint/README.md +++ b/avm/res/network/private-endpoint/README.md @@ -8,6 +8,7 @@ This module deploys a Private Endpoint. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types @@ -830,15 +831,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-customdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-customdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: Yes -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-customdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `customDnsConfigs.ipAddresses` @@ -847,6 +846,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -1022,7 +1028,7 @@ The resource id of private link service. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars. -- Required: Yes +- Required: No - Type: string ### Parameter: `privateDnsZoneGroup` @@ -1265,14 +1271,22 @@ Tags to be applied on all resources/resource groups in this deployment. | Output | Type | Description | | :-- | :-- | :-- | -| `customDnsConfig` | | The custom DNS configurations of the private endpoint. | +| `customDnsConfig` | array | The custom DNS configurations of the private endpoint. | | `groupId` | string | The group Id for the private endpoint Group. | | `location` | string | The location the resource was deployed into. | | `name` | string | The name of the private endpoint. | -| `networkInterfaceIds` | array | The IDs of the network interfaces associated with the private endpoint. | +| `networkInterfaceResourceIds` | array | The resource IDs of the network interfaces associated with the private endpoint. | | `resourceGroupName` | string | The resource group the private endpoint was deployed into. | | `resourceId` | string | The resource ID of the private endpoint. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/network/private-endpoint/main.bicep b/avm/res/network/private-endpoint/main.bicep index 8cc557c687..5ad5bde5ed 100644 --- a/avm/res/network/private-endpoint/main.bicep +++ b/avm/res/network/private-endpoint/main.bicep @@ -9,13 +9,13 @@ param name string param subnetResourceId string @description('Optional. Application security groups in which the private endpoint IP configuration is included.') -param applicationSecurityGroupResourceIds array? +param applicationSecurityGroupResourceIds string[]? @description('Optional. The custom name of the network interface attached to the private endpoint.') param customNetworkInterfaceName string? @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') -param ipConfigurations ipConfigurationsType +param ipConfigurations ipConfigurationType[]? @description('Optional. The private DNS zone group to configure for the private endpoint.') param privateDnsZoneGroup privateDnsZoneGroupType? @@ -23,23 +23,25 @@ param privateDnsZoneGroup privateDnsZoneGroupType? @description('Optional. Location for all Resources.') param location string = resourceGroup().location +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') param tags object? @description('Optional. Custom DNS configurations.') -param customDnsConfigs customDnsConfigType +param customDnsConfigs customDnsConfigType[]? @description('Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource.') -param manualPrivateLinkServiceConnections manualPrivateLinkServiceConnectionsType +param manualPrivateLinkServiceConnections manualPrivateLinkServiceConnectionType[]? @description('Optional. A grouping of information about the connection to the remote resource.') -param privateLinkServiceConnections privateLinkServiceConnectionsType +param privateLinkServiceConnections privateLinkServiceConnectionType[]? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true @@ -178,17 +180,13 @@ output name string = privateEndpoint.name output location string = privateEndpoint.location @description('The custom DNS configurations of the private endpoint.') -output customDnsConfig customDnsConfigType = privateEndpoint.properties.customDnsConfigs +output customDnsConfig customDnsConfigType[] = privateEndpoint.properties.customDnsConfigs -@description('The IDs of the network interfaces associated with the private endpoint.') -output networkInterfaceIds array = privateEndpoint.properties.networkInterfaces +@description('The resource IDs of the network interfaces associated with the private endpoint.') +output networkInterfaceResourceIds string[] = map(privateEndpoint.properties.networkInterfaces, nic => nic.id) @description('The group Id for the private endpoint Group.') -output groupId string = !empty(privateEndpoint.properties.manualPrivateLinkServiceConnections) && length(privateEndpoint.properties.manualPrivateLinkServiceConnections[0].properties.?groupIds) > 0 - ? privateEndpoint.properties.manualPrivateLinkServiceConnections[0].properties.?groupIds[0] ?? '' - : !empty(privateEndpoint.properties.privateLinkServiceConnections) && length(privateEndpoint.properties.privateLinkServiceConnections[0].properties.?groupIds) > 0 - ? privateEndpoint.properties.privateLinkServiceConnections[0].properties.?groupIds[0] ?? '' - : '' +output groupId string? = privateEndpoint.properties.?manualPrivateLinkServiceConnections[?0].properties.?groupIds[?0] ?? privateEndpoint.properties.?privateLinkServiceConnections[?0].properties.?groupIds[?0] // ================ // // Definitions // @@ -196,6 +194,7 @@ output groupId string = !empty(privateEndpoint.properties.manualPrivateLinkServi import { privateDnsZoneGroupConfigType } from 'private-dns-zone-group/main.bicep' +@export() type privateDnsZoneGroupType = { @description('Optional. The name of the Private DNS Zone Group.') name: string? @@ -204,41 +203,8 @@ type privateDnsZoneGroupType = { privateDnsZoneGroupConfigs: privateDnsZoneGroupConfigType[] } -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type ipConfigurationsType = { +@export() +type ipConfigurationType = { @description('Required. The name of the resource that is unique within a resource group.') name: string @@ -253,9 +219,10 @@ type ipConfigurationsType = { @description('Required. A private IP address obtained from the private endpoint\'s subnet.') privateIPAddress: string } -}[]? +} -type manualPrivateLinkServiceConnectionsType = { +@export() +type manualPrivateLinkServiceConnectionType = { @description('Required. The name of the private link service connection.') name: string @@ -268,11 +235,12 @@ type manualPrivateLinkServiceConnectionsType = { privateLinkServiceId: string @description('Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars.') - requestMessage: string + requestMessage: string? } -}[]? +} -type privateLinkServiceConnectionsType = { +@export() +type privateLinkServiceConnectionType = { @description('Required. The name of the private link service connection.') name: string @@ -287,12 +255,13 @@ type privateLinkServiceConnectionsType = { @description('Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars.') requestMessage: string? } -}[]? +} +@export() type customDnsConfigType = { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string + @description('Optional. FQDN that resolves to private endpoint IP address.') + fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') ipAddresses: string[] -}[]? +} diff --git a/avm/res/network/private-endpoint/main.json b/avm/res/network/private-endpoint/main.json index 3ccb1b2a1a..eb5ff7f266 100644 --- a/avm/res/network/private-endpoint/main.json +++ b/avm/res/network/private-endpoint/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2004143709646884954" + "version": "0.30.23.60470", + "templateHash": "602726199400096960" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -32,259 +32,192 @@ "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." } } + }, + "metadata": { + "__bicep_export!": true } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", + "ipConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "lockType": { + "manualPrivateLinkServiceConnectionType": { "type": "object", "properties": { "name": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Required. The name of the private link service connection." } }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "ipConfigurationsType": { - "type": "array", - "items": { - "type": "object", "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, + "type": "object", "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." - } + "groupIds": { + "type": "array", + "items": { + "type": "string" }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." } }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } } + }, + "metadata": { + "description": "Required. Properties of private link service connection." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "manualPrivateLinkServiceConnectionsType": { - "type": "array", - "items": { - "type": "object", + "privateLinkServiceConnectionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the private link service connection." - } - }, + "type": "object", "properties": { - "type": "object", - "properties": { - "groupIds": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." - } - }, - "privateLinkServiceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of private link service." - } + "groupIds": { + "type": "array", + "items": { + "type": "string" }, - "requestMessage": { - "type": "string", - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." - } + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." } }, - "metadata": { - "description": "Required. Properties of private link service connection." + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } } + }, + "metadata": { + "description": "Required. Properties of private link service connection." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "privateLinkServiceConnectionsType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the private link service connection." - } + "customDnsConfigType": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" }, - "properties": { - "type": "object", - "properties": { - "groupIds": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." - } - }, - "privateLinkServiceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of private link service." - } - }, - "requestMessage": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." - } - } - }, - "metadata": { - "description": "Required. Properties of private link service connection." - } + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "customDnsConfigType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "privateDnsZoneGroupConfigType": { "type": "object", @@ -308,6 +241,81 @@ "sourceTemplate": "private-dns-zone-group/main.bicep" } } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -325,6 +333,9 @@ }, "applicationSecurityGroupResourceIds": { "type": "array", + "items": { + "type": "string" + }, "nullable": true, "metadata": { "description": "Optional. Application security groups in which the private endpoint IP configuration is included." @@ -338,7 +349,11 @@ } }, "ipConfigurations": { - "$ref": "#/definitions/ipConfigurationsType", + "type": "array", + "items": { + "$ref": "#/definitions/ipConfigurationType" + }, + "nullable": true, "metadata": { "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } @@ -359,12 +374,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -377,19 +397,31 @@ } }, "customDnsConfigs": { - "$ref": "#/definitions/customDnsConfigType", + "type": "array", + "items": { + "$ref": "#/definitions/customDnsConfigType" + }, + "nullable": true, "metadata": { "description": "Optional. Custom DNS configurations." } }, "manualPrivateLinkServiceConnections": { - "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "type": "array", + "items": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionType" + }, + "nullable": true, "metadata": { "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." } }, "privateLinkServiceConnections": { - "$ref": "#/definitions/privateLinkServiceConnectionsType", + "type": "array", + "items": { + "$ref": "#/definitions/privateLinkServiceConnectionType" + }, + "nullable": true, "metadata": { "description": "Optional. A grouping of information about the connection to the remote resource." } @@ -534,8 +566,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5805178546717255803" + "version": "0.30.23.60470", + "templateHash": "12329174801198479603" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -683,25 +715,32 @@ "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" }, "customDnsConfig": { - "$ref": "#/definitions/customDnsConfigType", + "type": "array", + "items": { + "$ref": "#/definitions/customDnsConfigType" + }, "metadata": { "description": "The custom DNS configurations of the private endpoint." }, "value": "[reference('privateEndpoint').customDnsConfigs]" }, - "networkInterfaceIds": { + "networkInterfaceResourceIds": { "type": "array", + "items": { + "type": "string" + }, "metadata": { - "description": "The IDs of the network interfaces associated with the private endpoint." + "description": "The resource IDs of the network interfaces associated with the private endpoint." }, - "value": "[reference('privateEndpoint').networkInterfaces]" + "value": "[map(reference('privateEndpoint').networkInterfaces, lambda('nic', lambdaVariables('nic').id))]" }, "groupId": { "type": "string", + "nullable": true, "metadata": { "description": "The group Id for the private endpoint Group." }, - "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" + "value": "[coalesce(tryGet(tryGet(tryGet(tryGet(reference('privateEndpoint'), 'manualPrivateLinkServiceConnections'), 0, 'properties'), 'groupIds'), 0), tryGet(tryGet(tryGet(tryGet(reference('privateEndpoint'), 'privateLinkServiceConnections'), 0, 'properties'), 'groupIds'), 0))]" } } } \ No newline at end of file diff --git a/avm/res/network/private-endpoint/private-dns-zone-group/main.json b/avm/res/network/private-endpoint/private-dns-zone-group/main.json index c59c286088..30a4592a54 100644 --- a/avm/res/network/private-endpoint/private-dns-zone-group/main.json +++ b/avm/res/network/private-endpoint/private-dns-zone-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5805178546717255803" + "version": "0.30.23.60470", + "templateHash": "12329174801198479603" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", diff --git a/avm/res/network/private-endpoint/tests/e2e/defaults/main.test.bicep b/avm/res/network/private-endpoint/tests/e2e/defaults/main.test.bicep index 7d3610ac50..46628ddf32 100644 --- a/avm/res/network/private-endpoint/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/private-endpoint/tests/e2e/defaults/main.test.bicep @@ -17,9 +17,6 @@ param resourceLocation string = deployment().location @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') param serviceShort string = 'npemin' -@description('Generated. Used as a basis for unique resource names.') -param baseTime string = utcNow('u') - @description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') param namePrefix string = '#_namePrefix_#' @@ -39,7 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' params: { virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' location: resourceLocation } } diff --git a/avm/res/network/private-endpoint/tests/e2e/max/main.test.bicep b/avm/res/network/private-endpoint/tests/e2e/max/main.test.bicep index cfb7667b6f..71b57d3d12 100644 --- a/avm/res/network/private-endpoint/tests/e2e/max/main.test.bicep +++ b/avm/res/network/private-endpoint/tests/e2e/max/main.test.bicep @@ -17,9 +17,6 @@ param resourceLocation string = deployment().location @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') param serviceShort string = 'npemax' -@description('Generated. Used as a basis for unique resource names.') -param baseTime string = utcNow('u') - @description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') param namePrefix string = '#_namePrefix_#' @@ -39,7 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' params: { virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' applicationSecurityGroupName: 'dep-${namePrefix}-asg-${serviceShort}' location: resourceLocation diff --git a/avm/res/network/private-endpoint/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/private-endpoint/tests/e2e/waf-aligned/main.test.bicep index 9522b63077..5499bede2a 100644 --- a/avm/res/network/private-endpoint/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/private-endpoint/tests/e2e/waf-aligned/main.test.bicep @@ -17,9 +17,6 @@ param resourceLocation string = deployment().location @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') param serviceShort string = 'npewaf' -@description('Generated. Used as a basis for unique resource names.') -param baseTime string = utcNow('u') - @description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') param namePrefix string = '#_namePrefix_#' @@ -39,7 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' params: { virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' applicationSecurityGroupName: 'dep-${namePrefix}-asg-${serviceShort}' location: resourceLocation diff --git a/avm/res/network/private-endpoint/version.json b/avm/res/network/private-endpoint/version.json index 0f81d22abc..b8b30a0125 100644 --- a/avm/res/network/private-endpoint/version.json +++ b/avm/res/network/private-endpoint/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.8", + "version": "0.9", "pathFilters": [ "./main.json" ] diff --git a/avm/res/network/public-ip-address/README.md b/avm/res/network/public-ip-address/README.md index 8ba95ec8ab..b392a84ddd 100644 --- a/avm/res/network/public-ip-address/README.md +++ b/avm/res/network/public-ip-address/README.md @@ -8,6 +8,7 @@ This module deploys a Public IP Address. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types @@ -122,6 +123,12 @@ module publicIpAddress 'br/public:avm/res/network/public-ip-address:' = } ] dnsSettings: '' + ipTags: [ + { + ipTagType: 'RoutingPreference' + tag: 'Internet' + } + ] location: '' lock: { kind: 'CanNotDelete' @@ -199,6 +206,14 @@ module publicIpAddress 'br/public:avm/res/network/public-ip-address:' = "dnsSettings": { "value": "" }, + "ipTags": { + "value": [ + { + "ipTagType": "RoutingPreference", + "tag": "Internet" + } + ] + }, "location": { "value": "" }, @@ -286,6 +301,12 @@ param diagnosticSettings = [ } ] param dnsSettings = '' +param ipTags = [ + { + ipTagType: 'RoutingPreference' + tag: 'Internet' + } +] param location = '' param lock = { kind: 'CanNotDelete' @@ -576,6 +597,7 @@ param zones = [ | [`dnsSettings`](#parameter-dnssettings) | object | The DNS settings of the public IP address. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`idleTimeoutInMinutes`](#parameter-idletimeoutinminutes) | int | The idle timeout of the public IP address. | +| [`ipTags`](#parameter-iptags) | array | The list of tags associated with the public IP address. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`publicIPAddressVersion`](#parameter-publicipaddressversion) | string | IP address version. | @@ -663,7 +685,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -773,7 +795,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -867,6 +889,34 @@ The idle timeout of the public IP address. - Type: int - Default: `4` +### Parameter: `ipTags` + +The list of tags associated with the public IP address. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`ipTagType`](#parameter-iptagsiptagtype) | string | The IP tag type. | +| [`tag`](#parameter-iptagstag) | string | The IP tag. | + +### Parameter: `ipTags.ipTagType` + +The IP tag type. + +- Required: Yes +- Type: string + +### Parameter: `ipTags.tag` + +The IP tag. + +- Required: Yes +- Type: string + ### Parameter: `location` Location for all resources. @@ -1126,6 +1176,14 @@ A list of availability zones denoting the IP allocated for the resource needs to | `resourceGroupName` | string | The resource group the public IP address was deployed into. | | `resourceId` | string | The resource ID of the public IP address. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/network/public-ip-address/main.bicep b/avm/res/network/public-ip-address/main.bicep index 43a77d2454..923a8f1ccd 100644 --- a/avm/res/network/public-ip-address/main.bicep +++ b/avm/res/network/public-ip-address/main.bicep @@ -37,8 +37,12 @@ param publicIPAddressVersion string = 'IPv4' @description('Optional. The DNS settings of the public IP address.') param dnsSettings dnsSettingsType? +@description('Optional. The list of tags associated with the public IP address.') +param ipTags ipTagType[]? + +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? @description('Optional. Name of a public IP address SKU.') @allowed([ @@ -60,8 +64,9 @@ param ddosSettings ddosSettingsType? @description('Optional. Location for all resources.') param location string = resourceGroup().location +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true @@ -72,8 +77,9 @@ param idleTimeoutInMinutes int = 4 @description('Optional. Tags of the resource.') param tags object? +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -159,7 +165,7 @@ resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2023-09-01' = { } : null idleTimeoutInMinutes: idleTimeoutInMinutes - ipTags: null // Note: Requires feature 'Microsoft.Network/AllowBringYourOwnPublicIpAddress' to be registered on the subscription + ipTags: ipTags } } @@ -238,40 +244,7 @@ output location string = publicIpAddress.location // Definitions // // ================ // -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - +@export() type dnsSettingsType = { @description('Required. The domain name label. The concatenation of the domain name label and the regionalized DNS zone make up the fully qualified domain name associated with the public IP address. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system.') domainNameLabel: string @@ -286,6 +259,7 @@ type dnsSettingsType = { reverseFqdn: string? } +@export() type ddosSettingsType = { @description('Optional. The DDoS protection plan associated with the public IP address.') ddosProtectionPlan: { @@ -296,46 +270,11 @@ type ddosSettingsType = { protectionMode: 'Enabled' } -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? +@export() +type ipTagType = { + @description('Required. The IP tag type.') + ipTagType: string - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? + @description('Required. The IP tag.') + tag: string +} diff --git a/avm/res/network/public-ip-address/main.json b/avm/res/network/public-ip-address/main.json index 52d712a6d2..1052a87909 100644 --- a/avm/res/network/public-ip-address/main.json +++ b/avm/res/network/public-ip-address/main.json @@ -5,112 +5,14 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7554660773280925072" + "version": "0.30.23.60470", + "templateHash": "11325859316909755285" }, "name": "Public IP Addresses", "description": "This module deploys a Public IP Address.", "owner": "Azure/module-maintainers" }, "definitions": { - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, "dnsSettingsType": { "type": "object", "properties": { @@ -147,6 +49,9 @@ "description": "Optional. The reverse FQDN. A user-visible, fully qualified domain name that resolves to this public IP address. If the reverseFqdn is specified, then a PTR DNS record is created pointing from the IP address in the in-addr.arpa domain to the reverse FQDN." } } + }, + "metadata": { + "__bicep_export!": true } }, "ddosSettingsType": { @@ -176,127 +81,257 @@ "description": "Required. The DDoS protection policy customizations." } } + }, + "metadata": { + "__bicep_export!": true } }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "ipTagType": { + "type": "object", + "properties": { + "ipTagType": { + "type": "string", + "metadata": { + "description": "Required. The IP tag type." + } + }, + "tag": { + "type": "string", + "metadata": { + "description": "Required. The IP tag." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." } }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -361,8 +396,19 @@ "description": "Optional. The DNS settings of the public IP address." } }, + "ipTags": { + "type": "array", + "items": { + "$ref": "#/definitions/ipTagType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of tags associated with the public IP address." + } + }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } @@ -404,7 +450,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -431,7 +481,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -497,7 +551,7 @@ "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]", "publicIPPrefix": "[if(not(empty(parameters('publicIpPrefixResourceId'))), createObject('id', parameters('publicIpPrefixResourceId')), null())]", "idleTimeoutInMinutes": "[parameters('idleTimeoutInMinutes')]", - "ipTags": null + "ipTags": "[parameters('ipTags')]" } }, "publicIpAddress_lock": { diff --git a/avm/res/network/public-ip-address/tests/e2e/max/main.test.bicep b/avm/res/network/public-ip-address/tests/e2e/max/main.test.bicep index daea40b73e..02aed1e048 100644 --- a/avm/res/network/public-ip-address/tests/e2e/max/main.test.bicep +++ b/avm/res/network/public-ip-address/tests/e2e/max/main.test.bicep @@ -71,6 +71,12 @@ module testDeployment '../../../main.bicep' = [ } dnsSettings: null ddosSettings: null + ipTags: [ + { + ipTagType: 'RoutingPreference' + tag: 'Internet' + } + ] publicIpPrefixResourceId: null publicIPAllocationMethod: 'Static' roleAssignments: [ diff --git a/avm/res/network/public-ip-address/version.json b/avm/res/network/public-ip-address/version.json index e42c3d9e5f..09c3664cec 100644 --- a/avm/res/network/public-ip-address/version.json +++ b/avm/res/network/public-ip-address/version.json @@ -1,7 +1,7 @@ { - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.6", - "pathFilters": [ - "./main.json" - ] + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.7", + "pathFilters": [ + "./main.json" + ] } \ No newline at end of file diff --git a/avm/res/network/public-ip-prefix/README.md b/avm/res/network/public-ip-prefix/README.md index a61f1f8244..0b4c7cdd48 100644 --- a/avm/res/network/public-ip-prefix/README.md +++ b/avm/res/network/public-ip-prefix/README.md @@ -8,6 +8,7 @@ This module deploys a Public IP Prefix. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types @@ -16,7 +17,7 @@ This module deploys a Public IP Prefix. | :-- | :-- | | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | -| `Microsoft.Network/publicIPPrefixes` | [2023-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-09-01/publicIPPrefixes) | +| `Microsoft.Network/publicIPPrefixes` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/publicIPPrefixes) | ## Usage examples @@ -27,8 +28,9 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/network/public-ip-prefix:`. - [Using only defaults](#example-1-using-only-defaults) -- [Using large parameter set](#example-2-using-large-parameter-set) -- [WAF-aligned](#example-3-waf-aligned) +- [IPv6 Public IP Prefix](#example-2-ipv6-public-ip-prefix) +- [Using large parameter set](#example-3-using-large-parameter-set) +- [WAF-aligned](#example-4-waf-aligned) ### Example 1: _Using only defaults_ @@ -99,7 +101,81 @@ param location = ''

    -### Example 2: _Using large parameter set_ +### Example 2: _IPv6 Public IP Prefix_ + +This instance deploys the module using the IPv6 version of the Public IP Prefix. + + +

    + +via Bicep module + +```bicep +module publicIpPrefix 'br/public:avm/res/network/public-ip-prefix:' = { + name: 'publicIpPrefixDeployment' + params: { + // Required parameters + name: 'npipip6001' + prefixLength: 127 + // Non-required parameters + location: '' + publicIPAddressVersion: 'IPv6' + } +} +``` + +
    +

    + +

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

    + +

    + +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/network/public-ip-prefix:' + +// Required parameters +param name = 'npipip6001' +param prefixLength = 127 +// Non-required parameters +param location = '' +param publicIPAddressVersion = 'IPv6' +``` + +
    +

    + +### Example 3: _Using large parameter set_ This instance deploys the module with most of its features enabled. @@ -116,6 +192,12 @@ module publicIpPrefix 'br/public:avm/res/network/public-ip-prefix:' = { name: 'npipmax001' prefixLength: 28 // Non-required parameters + ipTags: [ + { + ipTagType: 'RoutingPreference' + tag: 'Internet' + } + ] location: '' lock: { kind: 'CanNotDelete' @@ -173,6 +255,14 @@ module publicIpPrefix 'br/public:avm/res/network/public-ip-prefix:' = { "value": 28 }, // Non-required parameters + "ipTags": { + "value": [ + { + "ipTagType": "RoutingPreference", + "tag": "Internet" + } + ] + }, "location": { "value": "" }, @@ -234,6 +324,12 @@ using 'br/public:avm/res/network/public-ip-prefix:' param name = 'npipmax001' param prefixLength = 28 // Non-required parameters +param ipTags = [ + { + ipTagType: 'RoutingPreference' + tag: 'Internet' + } +] param location = '' param lock = { kind: 'CanNotDelete' @@ -272,7 +368,7 @@ param zones = [

    -### Example 3: _WAF-aligned_ +### Example 4: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. @@ -373,11 +469,14 @@ param tags = { | :-- | :-- | :-- | | [`customIPPrefix`](#parameter-customipprefix) | object | The custom IP address prefix that this prefix is associated with. A custom IP address prefix is a contiguous range of IP addresses owned by an external customer and provisioned into a subscription. When a custom IP prefix is in Provisioned, Commissioning, or Commissioned state, a linked public IP prefix can be created. Either as a subset of the custom IP prefix range or the entire range. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`ipTags`](#parameter-iptags) | array | The list of tags associated with the public IP prefix. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`publicIPAddressVersion`](#parameter-publicipaddressversion) | string | The public IP address version. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | | [`tags`](#parameter-tags) | object | Tags of the resource. | -| [`zones`](#parameter-zones) | array | A list of availability zones denoting the IP allocated for the resource needs to come from. | +| [`tier`](#parameter-tier) | string | Tier of a public IP prefix SKU. If set to `Global`, the `zones` property must be empty. | +| [`zones`](#parameter-zones) | array | A list of availability zones denoting the IP allocated for the resource needs to come from. This is only applicable for regional public IP prefixes and must be empty for global public IP prefixes. | ### Parameter: `name` @@ -409,6 +508,34 @@ Enable/Disable usage telemetry for module. - Type: bool - Default: `True` +### Parameter: `ipTags` + +The list of tags associated with the public IP prefix. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`ipTagType`](#parameter-iptagsiptagtype) | string | The IP tag type. | +| [`tag`](#parameter-iptagstag) | string | The IP tag. | + +### Parameter: `ipTags.ipTagType` + +The IP tag type. + +- Required: Yes +- Type: string + +### Parameter: `ipTags.tag` + +The IP tag. + +- Required: Yes +- Type: string + ### Parameter: `location` Location for all resources. @@ -453,6 +580,21 @@ Specify the name of lock. - Required: No - Type: string +### Parameter: `publicIPAddressVersion` + +The public IP address version. + +- Required: No +- Type: string +- Default: `'IPv4'` +- Allowed: + ```Bicep + [ + 'IPv4' + 'IPv6' + ] + ``` + ### Parameter: `roleAssignments` Array of role assignments to create. @@ -564,9 +706,24 @@ Tags of the resource. - Required: No - Type: object +### Parameter: `tier` + +Tier of a public IP prefix SKU. If set to `Global`, the `zones` property must be empty. + +- Required: No +- Type: string +- Default: `'Regional'` +- Allowed: + ```Bicep + [ + 'Global' + 'Regional' + ] + ``` + ### Parameter: `zones` -A list of availability zones denoting the IP allocated for the resource needs to come from. +A list of availability zones denoting the IP allocated for the resource needs to come from. This is only applicable for regional public IP prefixes and must be empty for global public IP prefixes. - Required: No - Type: array @@ -596,6 +753,14 @@ A list of availability zones denoting the IP allocated for the resource needs to | `resourceGroupName` | string | The resource group the public IP prefix was deployed into. | | `resourceId` | string | The resource ID of the public IP prefix. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/network/public-ip-prefix/main.bicep b/avm/res/network/public-ip-prefix/main.bicep index f53aaf8b6c..3eb63b2270 100644 --- a/avm/res/network/public-ip-prefix/main.bicep +++ b/avm/res/network/public-ip-prefix/main.bicep @@ -6,19 +6,35 @@ metadata owner = 'Azure/module-maintainers' @minLength(1) param name string +@description('Optional. Tier of a public IP prefix SKU. If set to `Global`, the `zones` property must be empty.') +@allowed([ + 'Global' + 'Regional' +]) +param tier string = 'Regional' + @description('Optional. Location for all resources.') param location string = resourceGroup().location @description('Required. Length of the Public IP Prefix.') @minValue(21) -@maxValue(31) +@maxValue(127) param prefixLength int +@description('Optional. The public IP address version.') +@allowed([ + 'IPv4' + 'IPv6' +]) +param publicIPAddressVersion string = 'IPv4' + +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the resource.') param tags object? @@ -26,7 +42,10 @@ param tags object? @description('Optional. The custom IP address prefix that this prefix is associated with. A custom IP address prefix is a contiguous range of IP addresses owned by an external customer and provisioned into a subscription. When a custom IP prefix is in Provisioned, Commissioning, or Commissioned state, a linked public IP prefix can be created. Either as a subset of the custom IP prefix range or the entire range.') param customIPPrefix object = {} -@description('Optional. A list of availability zones denoting the IP allocated for the resource needs to come from.') +@description('Optional. The list of tags associated with the public IP prefix.') +param ipTags ipTagType[]? + +@description('Optional. A list of availability zones denoting the IP allocated for the resource needs to come from. This is only applicable for regional public IP prefixes and must be empty for global public IP prefixes.') @allowed([ 1 2 @@ -89,18 +108,20 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableT } } -resource publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2023-09-01' = { +resource publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2024-01-01' = { name: name location: location tags: tags sku: { name: 'Standard' + tier: tier } zones: map(zones, zone => string(zone)) properties: { customIPPrefix: !empty(customIPPrefix) ? customIPPrefix : null - publicIPAddressVersion: 'IPv4' + publicIPAddressVersion: publicIPAddressVersion prefixLength: prefixLength + ipTags: ipTags } } @@ -147,36 +168,11 @@ output location string = publicIpPrefix.location // Definitions // // =============== // -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? +@export() +type ipTagType = { + @description('Required. The IP tag type.') + ipTagType: string -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? + @description('Required. The IP tag.') + tag: string +} diff --git a/avm/res/network/public-ip-prefix/main.json b/avm/res/network/public-ip-prefix/main.json index 31a4295388..69abac3da9 100644 --- a/avm/res/network/public-ip-prefix/main.json +++ b/avm/res/network/public-ip-prefix/main.json @@ -6,13 +6,33 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "13346619343009869073" + "templateHash": "12984545577624848737" }, "name": "Public IP Prefixes", "description": "This module deploys a Public IP Prefix.", "owner": "Azure/module-maintainers" }, "definitions": { + "ipTagType": { + "type": "object", + "properties": { + "ipTagType": { + "type": "string", + "metadata": { + "description": "Required. The IP tag type." + } + }, + "tag": { + "type": "string", + "metadata": { + "description": "Required. The IP tag." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, "lockType": { "type": "object", "properties": { @@ -36,80 +56,87 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -120,6 +147,17 @@ "description": "Required. The name of the Public IP Prefix." } }, + "tier": { + "type": "string", + "defaultValue": "Regional", + "allowedValues": [ + "Global", + "Regional" + ], + "metadata": { + "description": "Optional. Tier of a public IP prefix SKU. If set to `Global`, the `zones` property must be empty." + } + }, "location": { "type": "string", "defaultValue": "[resourceGroup().location]", @@ -130,19 +168,35 @@ "prefixLength": { "type": "int", "minValue": 21, - "maxValue": 31, + "maxValue": 127, "metadata": { "description": "Required. Length of the Public IP Prefix." } }, + "publicIPAddressVersion": { + "type": "string", + "defaultValue": "IPv4", + "allowedValues": [ + "IPv4", + "IPv6" + ], + "metadata": { + "description": "Optional. The public IP address version." + } + }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -161,6 +215,16 @@ "description": "Optional. The custom IP address prefix that this prefix is associated with. A custom IP address prefix is a contiguous range of IP addresses owned by an external customer and provisioned into a subscription. When a custom IP prefix is in Provisioned, Commissioning, or Commissioned state, a linked public IP prefix can be created. Either as a subset of the custom IP prefix range or the entire range." } }, + "ipTags": { + "type": "array", + "items": { + "$ref": "#/definitions/ipTagType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of tags associated with the public IP prefix." + } + }, "zones": { "type": "array", "items": { @@ -177,7 +241,7 @@ 3 ], "metadata": { - "description": "Optional. A list of availability zones denoting the IP allocated for the resource needs to come from." + "description": "Optional. A list of availability zones denoting the IP allocated for the resource needs to come from. This is only applicable for regional public IP prefixes and must be empty for global public IP prefixes." } }, "enableTelemetry": { @@ -228,18 +292,20 @@ }, "publicIpPrefix": { "type": "Microsoft.Network/publicIPPrefixes", - "apiVersion": "2023-09-01", + "apiVersion": "2024-01-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", "sku": { - "name": "Standard" + "name": "Standard", + "tier": "[parameters('tier')]" }, "zones": "[map(parameters('zones'), lambda('zone', string(lambdaVariables('zone'))))]", "properties": { "customIPPrefix": "[if(not(empty(parameters('customIPPrefix'))), parameters('customIPPrefix'), null())]", - "publicIPAddressVersion": "IPv4", - "prefixLength": "[parameters('prefixLength')]" + "publicIPAddressVersion": "[parameters('publicIPAddressVersion')]", + "prefixLength": "[parameters('prefixLength')]", + "ipTags": "[parameters('ipTags')]" } }, "publicIpPrefix_lock": { @@ -306,7 +372,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('publicIpPrefix', '2023-09-01', 'full').location]" + "value": "[reference('publicIpPrefix', '2024-01-01', 'full').location]" } } } \ No newline at end of file diff --git a/avm/res/network/public-ip-prefix/tests/e2e/defaults/main.test.bicep b/avm/res/network/public-ip-prefix/tests/e2e/defaults/main.test.bicep index 271d5ed8ee..1c5839fb3c 100644 --- a/avm/res/network/public-ip-prefix/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/public-ip-prefix/tests/e2e/defaults/main.test.bicep @@ -26,7 +26,7 @@ param namePrefix string = '#_namePrefix_#' // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2023-07-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName location: resourceLocation } diff --git a/avm/res/network/public-ip-prefix/tests/e2e/ipv6/main.test.bicep b/avm/res/network/public-ip-prefix/tests/e2e/ipv6/main.test.bicep new file mode 100644 index 0000000000..701807e263 --- /dev/null +++ b/avm/res/network/public-ip-prefix/tests/e2e/ipv6/main.test.bicep @@ -0,0 +1,50 @@ +targetScope = 'subscription' + +metadata name = 'IPv6 Public IP Prefix' +metadata description = 'This instance deploys the module using the IPv6 version of the Public IP Prefix.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.publicipprefixes-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'npipip6' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + prefixLength: 127 + publicIPAddressVersion: 'IPv6' + } + } +] diff --git a/avm/res/network/public-ip-prefix/tests/e2e/max/main.test.bicep b/avm/res/network/public-ip-prefix/tests/e2e/max/main.test.bicep index 9e3d908bcb..c9148cc77e 100644 --- a/avm/res/network/public-ip-prefix/tests/e2e/max/main.test.bicep +++ b/avm/res/network/public-ip-prefix/tests/e2e/max/main.test.bicep @@ -26,7 +26,7 @@ param namePrefix string = '#_namePrefix_#' // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2023-07-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName location: resourceLocation } @@ -88,6 +88,12 @@ module testDeployment '../../../main.bicep' = [ 1 2 ] + ipTags: [ + { + ipTagType: 'RoutingPreference' + tag: 'Internet' + } + ] } } ] diff --git a/avm/res/network/public-ip-prefix/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/public-ip-prefix/tests/e2e/waf-aligned/main.test.bicep index 469fe72abf..ce435763ad 100644 --- a/avm/res/network/public-ip-prefix/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/public-ip-prefix/tests/e2e/waf-aligned/main.test.bicep @@ -26,7 +26,7 @@ param namePrefix string = '#_namePrefix_#' // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2023-07-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName location: resourceLocation } diff --git a/avm/res/network/public-ip-prefix/version.json b/avm/res/network/public-ip-prefix/version.json index a8eda31021..21226dd43f 100644 --- a/avm/res/network/public-ip-prefix/version.json +++ b/avm/res/network/public-ip-prefix/version.json @@ -1,7 +1,7 @@ { - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.5", - "pathFilters": [ - "./main.json" - ] + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.6", + "pathFilters": [ + "./main.json" + ] } \ No newline at end of file diff --git a/avm/res/network/virtual-hub/README.md b/avm/res/network/virtual-hub/README.md index 33a3d5861a..1f2cfbe4f6 100644 --- a/avm/res/network/virtual-hub/README.md +++ b/avm/res/network/virtual-hub/README.md @@ -18,7 +18,7 @@ If you are planning to deploy a Secure Virtual Hub (with an Azure Firewall integ | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Network/virtualHubs` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/virtualHubs) | | `Microsoft.Network/virtualHubs/hubRouteTables` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2022-11-01/virtualHubs/hubRouteTables) | -| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections) | +| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualHubs/hubVirtualNetworkConnections) | | `Microsoft.Network/virtualHubs/routingIntent` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/virtualHubs/routingIntent) | ## Usage examples diff --git a/avm/res/network/virtual-hub/hub-virtual-network-connection/README.md b/avm/res/network/virtual-hub/hub-virtual-network-connection/README.md index 256ef324ed..e5a1aca8d3 100644 --- a/avm/res/network/virtual-hub/hub-virtual-network-connection/README.md +++ b/avm/res/network/virtual-hub/hub-virtual-network-connection/README.md @@ -12,7 +12,7 @@ This module deploys a Virtual Hub Virtual Network Connection. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections) | +| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualHubs/hubVirtualNetworkConnections) | ## Parameters diff --git a/avm/res/network/virtual-network/README.md b/avm/res/network/virtual-network/README.md index 02339df598..517b60738f 100644 --- a/avm/res/network/virtual-network/README.md +++ b/avm/res/network/virtual-network/README.md @@ -13,6 +13,7 @@ This module deploys a Virtual Network (vNet). - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Notes](#Notes) - [Data Collection](#Data-Collection) @@ -23,9 +24,9 @@ This module deploys a Virtual Network (vNet). | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | -| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks) | -| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/subnets) | -| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/virtualNetworkPeerings) | +| `Microsoft.Network/virtualNetworks` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks) | +| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/subnets) | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/virtualNetworkPeerings) | ## Usage examples @@ -1178,7 +1179,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -1288,7 +1289,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -1716,9 +1717,10 @@ enable or disable apply network policies on private endpoint in the subnet. - Allowed: ```Bicep [ - '' 'Disabled' 'Enabled' + 'NetworkSecurityGroupEnabled' + 'RouteTableEnabled' ] ``` @@ -1731,7 +1733,6 @@ enable or disable apply network policies on private link service in the subnet. - Allowed: ```Bicep [ - '' 'Disabled' 'Enabled' ] @@ -1924,6 +1925,14 @@ If the encrypted VNet allows VM that does not support encryption. Can only be us | `subnetNames` | array | The names of the deployed subnets. | | `subnetResourceIds` | array | The resource IDs of the deployed subnets. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Notes ### Considerations diff --git a/avm/res/network/virtual-network/main.bicep b/avm/res/network/virtual-network/main.bicep index 1c667905c4..e991462e1f 100644 --- a/avm/res/network/virtual-network/main.bicep +++ b/avm/res/network/virtual-network/main.bicep @@ -40,14 +40,17 @@ param vnetEncryptionEnforcement string = 'AllowUnencrypted' @description('Optional. The flow timeout in minutes for the Virtual Network, which is used to enable connection tracking for intra-VM flows. Possible values are between 4 and 30 minutes. Default value 0 will set the property to null.') param flowTimeoutInMinutes int = 0 +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the resource.') param tags object? @@ -298,84 +301,6 @@ output location string = virtualNetwork.location // Definitions // // =============== // -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? - type peeringType = { @description('Optional. The Name of VNET Peering resource. If not provided, default value will be peer-localVnetName-remoteVnetName.') name: string? @@ -443,13 +368,13 @@ type subnetType = { networkSecurityGroupResourceId: string? @description('Optional. enable or disable apply network policies on private endpoint in the subnet.') - privateEndpointNetworkPolicies: ('Disabled' | 'Enabled' | '')? + privateEndpointNetworkPolicies: ('Disabled' | 'Enabled' | 'NetworkSecurityGroupEnabled' | 'RouteTableEnabled')? @description('Optional. enable or disable apply network policies on private link service in the subnet.') - privateLinkServiceNetworkPolicies: ('Disabled' | 'Enabled' | '')? + privateLinkServiceNetworkPolicies: ('Disabled' | 'Enabled')? @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType + roleAssignments: roleAssignmentType[]? @description('Optional. The resource ID of the route table to assign to the subnet.') routeTableResourceId: string? diff --git a/avm/res/network/virtual-network/main.json b/avm/res/network/virtual-network/main.json index 6e538351c9..70188e91b4 100644 --- a/avm/res/network/virtual-network/main.json +++ b/avm/res/network/virtual-network/main.json @@ -6,231 +6,13 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "9022073476687436734" + "templateHash": "17189690206142535748" }, "name": "Virtual Networks", "description": "This module deploys a Virtual Network (vNet).", "owner": "Azure/module-maintainers" }, "definitions": { - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } - } - } - }, - "nullable": true - }, "peeringType": { "type": "object", "properties": { @@ -393,9 +175,10 @@ "privateEndpointNetworkPolicies": { "type": "string", "allowedValues": [ - "", "Disabled", - "Enabled" + "Enabled", + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" ], "nullable": true, "metadata": { @@ -405,7 +188,6 @@ "privateLinkServiceNetworkPolicies": { "type": "string", "allowedValues": [ - "", "Disabled", "Enabled" ], @@ -415,7 +197,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -466,6 +252,233 @@ } } } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -559,19 +572,28 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -805,7 +827,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "6677157161292207910" + "templateHash": "6385219422012602265" }, "name": "Virtual Network Subnets", "description": "This module deploys a Virtual Network Subnet.", @@ -813,84 +835,86 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { "name": { "type": "string", "metadata": { - "description": "Requird. The Name of the subnet resource." + "description": "Required. The Name of the subnet resource." } }, "virtualNetworkName": { @@ -946,11 +970,12 @@ }, "privateEndpointNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", "Enabled", - "" + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private endpoint in the subnet." @@ -958,11 +983,10 @@ }, "privateLinkServiceNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", - "Enabled", - "" + "Enabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private link service in the subnet." @@ -1011,7 +1035,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -1061,8 +1089,8 @@ "routeTable": "[if(not(empty(parameters('routeTableResourceId'))), createObject('id', parameters('routeTableResourceId')), null())]", "natGateway": "[if(not(empty(parameters('natGatewayResourceId'))), createObject('id', parameters('natGatewayResourceId')), null())]", "delegations": "[if(not(empty(parameters('delegation'))), createArray(createObject('name', parameters('delegation'), 'properties', createObject('serviceName', parameters('delegation')))), createArray())]", - "privateEndpointNetworkPolicies": "[if(not(empty(parameters('privateEndpointNetworkPolicies'))), parameters('privateEndpointNetworkPolicies'), null())]", - "privateLinkServiceNetworkPolicies": "[if(not(empty(parameters('privateLinkServiceNetworkPolicies'))), parameters('privateLinkServiceNetworkPolicies'), null())]", + "privateEndpointNetworkPolicies": "[parameters('privateEndpointNetworkPolicies')]", + "privateLinkServiceNetworkPolicies": "[parameters('privateLinkServiceNetworkPolicies')]", "applicationGatewayIPConfigurations": "[parameters('applicationGatewayIPConfigurations')]", "serviceEndpointPolicies": "[parameters('serviceEndpointPolicies')]", "defaultOutboundAccess": "[parameters('defaultOutboundAccess')]", diff --git a/avm/res/network/virtual-network/subnet/README.md b/avm/res/network/virtual-network/subnet/README.md index 9a975d39da..9f36e460a2 100644 --- a/avm/res/network/virtual-network/subnet/README.md +++ b/avm/res/network/virtual-network/subnet/README.md @@ -14,10 +14,16 @@ This module deploys a Virtual Network Subnet. | Resource Type | API Version | | :-- | :-- | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | -| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/subnets) | +| `Microsoft.Network/virtualNetworks/subnets` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/subnets) | ## Parameters +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The Name of the subnet resource. | + **Conditional parameters** | Parameter | Type | Description | @@ -43,11 +49,12 @@ This module deploys a Virtual Network Subnet. | [`serviceEndpoints`](#parameter-serviceendpoints) | array | The service endpoints to enable on the subnet. | | [`sharingScope`](#parameter-sharingscope) | string | Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty. | -**Requird parameters** +### Parameter: `name` -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`name`](#parameter-name) | string | The Name of the subnet resource. | +The Name of the subnet resource. + +- Required: Yes +- Type: string ### Parameter: `addressPrefix` @@ -112,13 +119,13 @@ Enable or disable apply network policies on private endpoint in the subnet. - Required: No - Type: string -- Default: `''` - Allowed: ```Bicep [ - '' 'Disabled' 'Enabled' + 'NetworkSecurityGroupEnabled' + 'RouteTableEnabled' ] ``` @@ -128,11 +135,9 @@ Enable or disable apply network policies on private link service in the subnet. - Required: No - Type: string -- Default: `''` - Allowed: ```Bicep [ - '' 'Disabled' 'Enabled' ] @@ -279,13 +284,6 @@ Set this property to Tenant to allow sharing subnet with other subscriptions in ] ``` -### Parameter: `name` - -The Name of the subnet resource. - -- Required: Yes -- Type: string - ## Outputs | Output | Type | Description | diff --git a/avm/res/network/virtual-network/subnet/main.bicep b/avm/res/network/virtual-network/subnet/main.bicep index a51b2d7c59..069b8887ae 100644 --- a/avm/res/network/virtual-network/subnet/main.bicep +++ b/avm/res/network/virtual-network/subnet/main.bicep @@ -2,7 +2,7 @@ metadata name = 'Virtual Network Subnets' metadata description = 'This module deploys a Virtual Network Subnet.' metadata owner = 'Azure/module-maintainers' -@description('Requird. The Name of the subnet resource.') +@description('Required. The Name of the subnet resource.') param name string @description('Conditional. The name of the parent virtual network. Required if the template is used in a standalone deployment.') @@ -30,17 +30,17 @@ param natGatewayResourceId string? @allowed([ 'Disabled' 'Enabled' - '' + 'NetworkSecurityGroupEnabled' + 'RouteTableEnabled' ]) -param privateEndpointNetworkPolicies string = '' +param privateEndpointNetworkPolicies string? @description('Optional. Enable or disable apply network policies on private link service in the subnet.') @allowed([ 'Disabled' 'Enabled' - '' ]) -param privateLinkServiceNetworkPolicies string = '' +param privateLinkServiceNetworkPolicies string? @description('Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty.') param addressPrefixes string[]? @@ -57,8 +57,9 @@ param applicationGatewayIPConfigurations array = [] @description('Optional. An array of service endpoint policies.') param serviceEndpointPolicies array = [] +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -129,10 +130,8 @@ resource subnet 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' = { } ] : [] - privateEndpointNetworkPolicies: !empty(privateEndpointNetworkPolicies) ? any(privateEndpointNetworkPolicies) : null - privateLinkServiceNetworkPolicies: !empty(privateLinkServiceNetworkPolicies) - ? any(privateLinkServiceNetworkPolicies) - : null + privateEndpointNetworkPolicies: privateEndpointNetworkPolicies + privateLinkServiceNetworkPolicies: privateLinkServiceNetworkPolicies applicationGatewayIPConfigurations: applicationGatewayIPConfigurations serviceEndpointPolicies: serviceEndpointPolicies defaultOutboundAccess: defaultOutboundAccess @@ -170,33 +169,3 @@ output addressPrefix string = subnet.properties.?addressPrefix ?? '' @description('List of address prefixes for the subnet.') output addressPrefixes array = subnet.properties.?addressPrefixes ?? [] - -// =============== // -// Definitions // -// =============== // - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/network/virtual-network/subnet/main.json b/avm/res/network/virtual-network/subnet/main.json index 09fb7ed1de..4fdc5bc155 100644 --- a/avm/res/network/virtual-network/subnet/main.json +++ b/avm/res/network/virtual-network/subnet/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "6677157161292207910" + "templateHash": "6385219422012602265" }, "name": "Virtual Network Subnets", "description": "This module deploys a Virtual Network Subnet.", @@ -14,84 +14,86 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { "name": { "type": "string", "metadata": { - "description": "Requird. The Name of the subnet resource." + "description": "Required. The Name of the subnet resource." } }, "virtualNetworkName": { @@ -147,11 +149,12 @@ }, "privateEndpointNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", "Enabled", - "" + "NetworkSecurityGroupEnabled", + "RouteTableEnabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private endpoint in the subnet." @@ -159,11 +162,10 @@ }, "privateLinkServiceNetworkPolicies": { "type": "string", - "defaultValue": "", + "nullable": true, "allowedValues": [ "Disabled", - "Enabled", - "" + "Enabled" ], "metadata": { "description": "Optional. Enable or disable apply network policies on private link service in the subnet." @@ -212,7 +214,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -262,8 +268,8 @@ "routeTable": "[if(not(empty(parameters('routeTableResourceId'))), createObject('id', parameters('routeTableResourceId')), null())]", "natGateway": "[if(not(empty(parameters('natGatewayResourceId'))), createObject('id', parameters('natGatewayResourceId')), null())]", "delegations": "[if(not(empty(parameters('delegation'))), createArray(createObject('name', parameters('delegation'), 'properties', createObject('serviceName', parameters('delegation')))), createArray())]", - "privateEndpointNetworkPolicies": "[if(not(empty(parameters('privateEndpointNetworkPolicies'))), parameters('privateEndpointNetworkPolicies'), null())]", - "privateLinkServiceNetworkPolicies": "[if(not(empty(parameters('privateLinkServiceNetworkPolicies'))), parameters('privateLinkServiceNetworkPolicies'), null())]", + "privateEndpointNetworkPolicies": "[parameters('privateEndpointNetworkPolicies')]", + "privateLinkServiceNetworkPolicies": "[parameters('privateLinkServiceNetworkPolicies')]", "applicationGatewayIPConfigurations": "[parameters('applicationGatewayIPConfigurations')]", "serviceEndpointPolicies": "[parameters('serviceEndpointPolicies')]", "defaultOutboundAccess": "[parameters('defaultOutboundAccess')]", diff --git a/avm/res/network/virtual-network/version.json b/avm/res/network/virtual-network/version.json index 13669e6601..ea4f3b6e67 100644 --- a/avm/res/network/virtual-network/version.json +++ b/avm/res/network/virtual-network/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.5", "pathFilters": [ "./main.json" ] diff --git a/avm/res/network/virtual-network/virtual-network-peering/README.md b/avm/res/network/virtual-network/virtual-network-peering/README.md index 5c61182dc1..ef10225be1 100644 --- a/avm/res/network/virtual-network/virtual-network-peering/README.md +++ b/avm/res/network/virtual-network/virtual-network-peering/README.md @@ -12,7 +12,7 @@ This module deploys a Virtual Network Peering. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/virtualNetworks/virtualNetworkPeerings) | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/virtualNetworks/virtualNetworkPeerings) | ## Parameters diff --git a/avm/res/operational-insights/workspace/README.md b/avm/res/operational-insights/workspace/README.md index 40a8d48755..c852991208 100644 --- a/avm/res/operational-insights/workspace/README.md +++ b/avm/res/operational-insights/workspace/README.md @@ -27,6 +27,7 @@ This module deploys a Log Analytics Workspace. | `Microsoft.OperationalInsights/workspaces/storageInsightConfigs` | [2020-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/storageInsightConfigs) | | `Microsoft.OperationalInsights/workspaces/tables` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2022-10-01/workspaces/tables) | | `Microsoft.OperationsManagement/solutions` | [2015-11-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationsManagement/2015-11-01-preview/solutions) | +| `Microsoft.SecurityInsights/onboardingStates` | [2024-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.SecurityInsights/onboardingStates) | ## Usage examples @@ -199,9 +200,10 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = ] gallerySolutions: [ { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'AzureAutomation(oiwadv001)' + plan: { + product: 'OMSGallery/AzureAutomation' + } } ] linkedServices: [ @@ -213,7 +215,9 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = linkedStorageAccounts: [ { name: 'Query' - resourceId: '' + storageAccountIds: [ + '' + ] } ] location: '' @@ -268,11 +272,11 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'RawData' - type: 'String' + type: 'string' } ] name: 'CustomTableBasic_CL' @@ -302,27 +306,27 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'EventTime' - type: 'DateTime' + type: 'dateTime' } { name: 'EventLevel' - type: 'String' + type: 'string' } { name: 'EventCode' - type: 'Int' + type: 'int' } { name: 'Message' - type: 'String' + type: 'string' } { name: 'RawData' - type: 'String' + type: 'string' } ] name: 'CustomTableAdvanced_CL' @@ -507,9 +511,10 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "gallerySolutions": { "value": [ { - "name": "AzureAutomation", - "product": "OMSGallery", - "publisher": "Microsoft" + "name": "AzureAutomation(oiwadv001)", + "plan": { + "product": "OMSGallery/AzureAutomation" + } } ] }, @@ -525,7 +530,9 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "value": [ { "name": "Query", - "resourceId": "" + "storageAccountIds": [ + "" + ] } ] }, @@ -594,11 +601,11 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "columns": [ { "name": "TimeGenerated", - "type": "DateTime" + "type": "dateTime" }, { "name": "RawData", - "type": "String" + "type": "string" } ], "name": "CustomTableBasic_CL" @@ -628,27 +635,27 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "columns": [ { "name": "TimeGenerated", - "type": "DateTime" + "type": "dateTime" }, { "name": "EventTime", - "type": "DateTime" + "type": "dateTime" }, { "name": "EventLevel", - "type": "String" + "type": "string" }, { "name": "EventCode", - "type": "Int" + "type": "int" }, { "name": "Message", - "type": "String" + "type": "string" }, { "name": "RawData", - "type": "String" + "type": "string" } ], "name": "CustomTableAdvanced_CL" @@ -825,9 +832,10 @@ param diagnosticSettings = [ ] param gallerySolutions = [ { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'AzureAutomation(oiwadv001)' + plan: { + product: 'OMSGallery/AzureAutomation' + } } ] param linkedServices = [ @@ -839,7 +847,9 @@ param linkedServices = [ param linkedStorageAccounts = [ { name: 'Query' - resourceId: '' + storageAccountIds: [ + '' + ] } ] param location = '' @@ -894,11 +904,11 @@ param tables = [ columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'RawData' - type: 'String' + type: 'string' } ] name: 'CustomTableBasic_CL' @@ -928,27 +938,27 @@ param tables = [ columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'EventTime' - type: 'DateTime' + type: 'dateTime' } { name: 'EventLevel' - type: 'String' + type: 'string' } { name: 'EventCode' - type: 'Int' + type: 'int' } { name: 'Message' - type: 'String' + type: 'string' } { name: 'RawData' - type: 'String' + type: 'string' } ] name: 'CustomTableAdvanced_CL' @@ -1153,9 +1163,25 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = ] gallerySolutions: [ { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'AzureAutomation(oiwmax001)' + plan: { + product: 'OMSGallery/AzureAutomation' + } + } + { + name: 'SecurityInsights(oiwmax001)' + plan: { + product: 'OMSGallery/SecurityInsights' + publisher: 'Microsoft' + } + } + { + name: 'SQLAuditing(oiwmax001)' + plan: { + name: 'SQLAuditing(oiwmax001)' + product: 'SQLAuditing' + publisher: 'Microsoft' + } } ] linkedServices: [ @@ -1167,7 +1193,9 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = linkedStorageAccounts: [ { name: 'Query' - resourceId: '' + storageAccountIds: [ + '' + ] } ] location: '' @@ -1178,6 +1206,7 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = managedIdentities: { systemAssigned: true } + onboardWorkspaceToSentinel: true publicNetworkAccessForIngestion: 'Disabled' publicNetworkAccessForQuery: 'Disabled' roleAssignments: [ @@ -1253,11 +1282,11 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'RawData' - type: 'String' + type: 'string' } ] name: 'CustomTableBasic_CL' @@ -1287,27 +1316,27 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'EventTime' - type: 'DateTime' + type: 'dateTime' } { name: 'EventLevel' - type: 'String' + type: 'string' } { name: 'EventCode' - type: 'Int' + type: 'int' } { name: 'Message' - type: 'String' + type: 'string' } { name: 'RawData' - type: 'String' + type: 'string' } ] name: 'CustomTableAdvanced_CL' @@ -1455,9 +1484,25 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "gallerySolutions": { "value": [ { - "name": "AzureAutomation", - "product": "OMSGallery", - "publisher": "Microsoft" + "name": "AzureAutomation(oiwmax001)", + "plan": { + "product": "OMSGallery/AzureAutomation" + } + }, + { + "name": "SecurityInsights(oiwmax001)", + "plan": { + "product": "OMSGallery/SecurityInsights", + "publisher": "Microsoft" + } + }, + { + "name": "SQLAuditing(oiwmax001)", + "plan": { + "name": "SQLAuditing(oiwmax001)", + "product": "SQLAuditing", + "publisher": "Microsoft" + } } ] }, @@ -1473,7 +1518,9 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "value": [ { "name": "Query", - "resourceId": "" + "storageAccountIds": [ + "" + ] } ] }, @@ -1491,6 +1538,9 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "systemAssigned": true } }, + "onboardWorkspaceToSentinel": { + "value": true + }, "publicNetworkAccessForIngestion": { "value": "Disabled" }, @@ -1577,11 +1627,11 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "columns": [ { "name": "TimeGenerated", - "type": "DateTime" + "type": "dateTime" }, { "name": "RawData", - "type": "String" + "type": "string" } ], "name": "CustomTableBasic_CL" @@ -1611,27 +1661,27 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "columns": [ { "name": "TimeGenerated", - "type": "DateTime" + "type": "dateTime" }, { "name": "EventTime", - "type": "DateTime" + "type": "dateTime" }, { "name": "EventLevel", - "type": "String" + "type": "string" }, { "name": "EventCode", - "type": "Int" + "type": "int" }, { "name": "Message", - "type": "String" + "type": "string" }, { "name": "RawData", - "type": "String" + "type": "string" } ], "name": "CustomTableAdvanced_CL" @@ -1773,9 +1823,25 @@ param diagnosticSettings = [ ] param gallerySolutions = [ { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'AzureAutomation(oiwmax001)' + plan: { + product: 'OMSGallery/AzureAutomation' + } + } + { + name: 'SecurityInsights(oiwmax001)' + plan: { + product: 'OMSGallery/SecurityInsights' + publisher: 'Microsoft' + } + } + { + name: 'SQLAuditing(oiwmax001)' + plan: { + name: 'SQLAuditing(oiwmax001)' + product: 'SQLAuditing' + publisher: 'Microsoft' + } } ] param linkedServices = [ @@ -1787,7 +1853,9 @@ param linkedServices = [ param linkedStorageAccounts = [ { name: 'Query' - resourceId: '' + storageAccountIds: [ + '' + ] } ] param location = '' @@ -1798,6 +1866,7 @@ param lock = { param managedIdentities = { systemAssigned: true } +param onboardWorkspaceToSentinel = true param publicNetworkAccessForIngestion = 'Disabled' param publicNetworkAccessForQuery = 'Disabled' param roleAssignments = [ @@ -1873,11 +1942,11 @@ param tables = [ columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'RawData' - type: 'String' + type: 'string' } ] name: 'CustomTableBasic_CL' @@ -1907,27 +1976,27 @@ param tables = [ columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'EventTime' - type: 'DateTime' + type: 'dateTime' } { name: 'EventLevel' - type: 'String' + type: 'string' } { name: 'EventCode' - type: 'Int' + type: 'int' } { name: 'Message' - type: 'String' + type: 'string' } { name: 'RawData' - type: 'String' + type: 'string' } ] name: 'CustomTableAdvanced_CL' @@ -2062,9 +2131,10 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = ] gallerySolutions: [ { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'AzureAutomation(oiwwaf001)' + plan: { + product: 'OMSGallery/AzureAutomation' + } } ] linkedServices: [ @@ -2076,7 +2146,9 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = linkedStorageAccounts: [ { name: 'Query' - resourceId: '' + storageAccountIds: [ + '' + ] } ] location: '' @@ -2231,9 +2303,10 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "gallerySolutions": { "value": [ { - "name": "AzureAutomation", - "product": "OMSGallery", - "publisher": "Microsoft" + "name": "AzureAutomation(oiwwaf001)", + "plan": { + "product": "OMSGallery/AzureAutomation" + } } ] }, @@ -2249,7 +2322,9 @@ module workspace 'br/public:avm/res/operational-insights/workspace:' = "value": [ { "name": "Query", - "resourceId": "" + "storageAccountIds": [ + "" + ] } ] }, @@ -2408,9 +2483,10 @@ param diagnosticSettings = [ ] param gallerySolutions = [ { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'AzureAutomation(oiwwaf001)' + plan: { + product: 'OMSGallery/AzureAutomation' + } } ] param linkedServices = [ @@ -2422,7 +2498,9 @@ param linkedServices = [ param linkedStorageAccounts = [ { name: 'Query' - resourceId: '' + storageAccountIds: [ + '' + ] } ] param location = '' @@ -2483,6 +2561,7 @@ param useResourcePermissions = true | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both. | +| [`onboardWorkspaceToSentinel`](#parameter-onboardworkspacetosentinel) | bool | Onboard the Log Analytics Workspace to Sentinel. Requires 'SecurityInsights' solution to be in gallerySolutions. | | [`publicNetworkAccessForIngestion`](#parameter-publicnetworkaccessforingestion) | string | The network access type for accessing Log Analytics ingestion. | | [`publicNetworkAccessForQuery`](#parameter-publicnetworkaccessforquery) | string | The network access type for accessing Log Analytics query. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | @@ -2507,7 +2586,27 @@ List of Storage Accounts to be linked. Required if 'forceCmkForQuery' is set to - Required: No - Type: array -- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-linkedstorageaccountsname) | string | Name of the link. | +| [`storageAccountIds`](#parameter-linkedstorageaccountsstorageaccountids) | array | Linked storage accounts resources Ids. | + +### Parameter: `linkedStorageAccounts.name` + +Name of the link. + +- Required: Yes +- Type: string + +### Parameter: `linkedStorageAccounts.storageAccountIds` + +Linked storage accounts resources Ids. + +- Required: Yes +- Type: array ### Parameter: `dailyQuotaGb` @@ -2523,7 +2622,87 @@ LAW data export instances to be deployed. - Required: No - Type: array -- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-dataexportsname) | string | Name of the data export. | +| [`tableNames`](#parameter-dataexportstablenames) | array | The list of table names to export. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`destination`](#parameter-dataexportsdestination) | object | The destination of the data export. | +| [`enable`](#parameter-dataexportsenable) | bool | Enable or disable the data export. | + +### Parameter: `dataExports.name` + +Name of the data export. + +- Required: Yes +- Type: string + +### Parameter: `dataExports.tableNames` + +The list of table names to export. + +- Required: Yes +- Type: array + +### Parameter: `dataExports.destination` + +The destination of the data export. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`resourceId`](#parameter-dataexportsdestinationresourceid) | string | The destination resource ID. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`metaData`](#parameter-dataexportsdestinationmetadata) | object | The destination metadata. | + +### Parameter: `dataExports.destination.resourceId` + +The destination resource ID. + +- Required: Yes +- Type: string + +### Parameter: `dataExports.destination.metaData` + +The destination metadata. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`eventHubName`](#parameter-dataexportsdestinationmetadataeventhubname) | string | Allows to define an Event Hub name. Not applicable when destination is Storage Account. | + +### Parameter: `dataExports.destination.metaData.eventHubName` + +Allows to define an Event Hub name. Not applicable when destination is Storage Account. + +- Required: No +- Type: string + +### Parameter: `dataExports.enable` + +Enable or disable the data export. + +- Required: No +- Type: bool ### Parameter: `dataRetention` @@ -2539,7 +2718,128 @@ LAW data sources to configure. - Required: No - Type: array -- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-datasourceskind) | string | The kind of data source. | +| [`name`](#parameter-datasourcesname) | string | Name of the data source. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`counterName`](#parameter-datasourcescountername) | string | Counter name to configure when kind is WindowsPerformanceCounter. | +| [`eventLogName`](#parameter-datasourceseventlogname) | string | The name of the event log to configure when kind is WindowsEvent. | +| [`eventTypes`](#parameter-datasourceseventtypes) | array | The event types to configure when kind is WindowsEvent. | +| [`instanceName`](#parameter-datasourcesinstancename) | string | Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| [`intervalSeconds`](#parameter-datasourcesintervalseconds) | int | Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| [`linkedResourceId`](#parameter-datasourceslinkedresourceid) | string | The resource id of the resource that will be linked to the workspace. | +| [`objectName`](#parameter-datasourcesobjectname) | string | Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| [`performanceCounters`](#parameter-datasourcesperformancecounters) | array | List of counters to configure when the kind is LinuxPerformanceObject. | +| [`state`](#parameter-datasourcesstate) | string | State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection. | +| [`syslogName`](#parameter-datasourcessyslogname) | string | System log to configure when kind is LinuxSyslog. | +| [`syslogSeverities`](#parameter-datasourcessyslogseverities) | array | Severities to configure when kind is LinuxSyslog. | +| [`tags`](#parameter-datasourcestags) | object | Tags to configure in the resource. | + +### Parameter: `dataSources.kind` + +The kind of data source. + +- Required: Yes +- Type: string + +### Parameter: `dataSources.name` + +Name of the data source. + +- Required: Yes +- Type: string + +### Parameter: `dataSources.counterName` + +Counter name to configure when kind is WindowsPerformanceCounter. + +- Required: No +- Type: string + +### Parameter: `dataSources.eventLogName` + +The name of the event log to configure when kind is WindowsEvent. + +- Required: No +- Type: string + +### Parameter: `dataSources.eventTypes` + +The event types to configure when kind is WindowsEvent. + +- Required: No +- Type: array + +### Parameter: `dataSources.instanceName` + +Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. + +- Required: No +- Type: string + +### Parameter: `dataSources.intervalSeconds` + +Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. + +- Required: No +- Type: int + +### Parameter: `dataSources.linkedResourceId` + +The resource id of the resource that will be linked to the workspace. + +- Required: No +- Type: string + +### Parameter: `dataSources.objectName` + +Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. + +- Required: No +- Type: string + +### Parameter: `dataSources.performanceCounters` + +List of counters to configure when the kind is LinuxPerformanceObject. + +- Required: No +- Type: array + +### Parameter: `dataSources.state` + +State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection. + +- Required: No +- Type: string + +### Parameter: `dataSources.syslogName` + +System log to configure when kind is LinuxSyslog. + +- Required: No +- Type: string + +### Parameter: `dataSources.syslogSeverities` + +Severities to configure when kind is LinuxSyslog. + +- Required: No +- Type: array + +### Parameter: `dataSources.tags` + +Tags to configure in the resource. + +- Required: No +- Type: object ### Parameter: `diagnosticSettings` @@ -2717,88 +3017,183 @@ List of gallerySolutions to be created in the log analytics workspace. - Required: No - Type: array -- Default: `[]` -### Parameter: `linkedServices` - -List of services to be linked. +**Required parameters** -- Required: No -- Type: array -- Default: `[]` +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-gallerysolutionsname) | string | Name of the solution.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.

    The solution type is case-sensitive. | +| [`plan`](#parameter-gallerysolutionsplan) | object | Plan for solution object supported by the OperationsManagement resource provider. | -### Parameter: `location` +### Parameter: `gallerySolutions.name` -Location for all resources. +Name of the solution.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.

    The solution type is case-sensitive. -- Required: No +- Required: Yes - Type: string -- Default: `[resourceGroup().location]` -### Parameter: `lock` +### Parameter: `gallerySolutions.plan` -The lock settings of the service. +Plan for solution object supported by the OperationsManagement resource provider. -- Required: No +- Required: Yes - Type: object +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`product`](#parameter-gallerysolutionsplanproduct) | string | The product name of the deployed solution.

    For Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.

    For a third party solution, it can be anything.

    This is case sensitive. | + **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | -| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | -| [`name`](#parameter-lockname) | string | Specify the name of lock. | +| [`name`](#parameter-gallerysolutionsplanname) | string | Name of the solution to be created.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, it can be anything.

    The solution type is case-sensitive.

    If not provided, the value of the `name` parameter will be used. | +| [`publisher`](#parameter-gallerysolutionsplanpublisher) | string | The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value. | -### Parameter: `lock.kind` +### Parameter: `gallerySolutions.plan.product` -Specify the type of lock. +The product name of the deployed solution.

    For Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.

    For a third party solution, it can be anything.

    This is case sensitive. + +- Required: Yes +- Type: string + +### Parameter: `gallerySolutions.plan.name` + +Name of the solution to be created.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, it can be anything.

    The solution type is case-sensitive.

    If not provided, the value of the `name` parameter will be used. - Required: No - Type: string -- Allowed: - ```Bicep - [ - 'CanNotDelete' - 'None' - 'ReadOnly' - ] - ``` -### Parameter: `lock.name` +### Parameter: `gallerySolutions.plan.publisher` -Specify the name of lock. +The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value. - Required: No - Type: string -### Parameter: `managedIdentities` +### Parameter: `linkedServices` -The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both. +List of services to be linked. - Required: No -- Type: object +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-linkedservicesname) | string | Name of the linked service. | **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | -| [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | +| [`resourceId`](#parameter-linkedservicesresourceid) | 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. | +| [`writeAccessResourceId`](#parameter-linkedserviceswriteaccessresourceid) | 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: `managedIdentities.systemAssigned` +### Parameter: `linkedServices.name` -Enables system assigned managed identity on the resource. +Name of the linked service. -- Required: No +- Required: Yes +- Type: string + +### Parameter: `linkedServices.resourceId` + +The resource id of the resource that will be linked to the workspace. This should be used for linking resources which require read access. + +- Required: No +- Type: string + +### Parameter: `linkedServices.writeAccessResourceId` + +The resource id of the resource that will be linked to the workspace. This should be used for linking resources which require write access. + +- Required: No +- Type: string + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `managedIdentities` + +The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | + +### Parameter: `managedIdentities.systemAssigned` + +Enables system assigned managed identity on the resource. + +- Required: No - Type: bool ### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. - Required: No - Type: array +### Parameter: `onboardWorkspaceToSentinel` + +Onboard the Log Analytics Workspace to Sentinel. Requires 'SecurityInsights' solution to be in gallerySolutions. + +- Required: No +- Type: bool +- Default: `False` + ### Parameter: `publicNetworkAccessForIngestion` The network access type for accessing Log Analytics ingestion. @@ -2944,7 +3339,88 @@ Kusto Query Language searches to save. - Required: No - Type: array -- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`category`](#parameter-savedsearchescategory) | string | The category of the saved search. This helps the user to find a saved search faster. | +| [`displayName`](#parameter-savedsearchesdisplayname) | string | Display name for the search. | +| [`name`](#parameter-savedsearchesname) | string | Name of the saved search. | +| [`query`](#parameter-savedsearchesquery) | string | The query expression for the saved search. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`etag`](#parameter-savedsearchesetag) | string | The ETag of the saved search. To override an existing saved search, use "*" or specify the current Etag. | +| [`functionAlias`](#parameter-savedsearchesfunctionalias) | string | The function alias if query serves as a function. | +| [`functionParameters`](#parameter-savedsearchesfunctionparameters) | 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`](#parameter-savedsearchestags) | array | The tags attached to the saved search. | +| [`version`](#parameter-savedsearchesversion) | int | The version number of the query language. The current version is 2 and is the default. | + +### Parameter: `savedSearches.category` + +The category of the saved search. This helps the user to find a saved search faster. + +- Required: Yes +- Type: string + +### Parameter: `savedSearches.displayName` + +Display name for the search. + +- Required: Yes +- Type: string + +### Parameter: `savedSearches.name` + +Name of the saved search. + +- Required: Yes +- Type: string + +### Parameter: `savedSearches.query` + +The query expression for the saved search. + +- Required: Yes +- Type: string + +### Parameter: `savedSearches.etag` + +The ETag of the saved search. To override an existing saved search, use "*" or specify the current Etag. + +- Required: No +- Type: string + +### Parameter: `savedSearches.functionAlias` + +The function alias if query serves as a function. + +- Required: No +- Type: string + +### Parameter: `savedSearches.functionParameters` + +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. + +- Required: No +- Type: string + +### Parameter: `savedSearches.tags` + +The tags attached to the saved search. + +- Required: No +- Type: array + +### Parameter: `savedSearches.version` + +The version number of the query language. The current version is 2 and is the default. + +- Required: No +- Type: int ### Parameter: `skuCapacityReservationLevel` @@ -2981,7 +3457,40 @@ List of storage accounts to be read by the workspace. - Required: No - Type: array -- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`storageAccountResourceId`](#parameter-storageinsightsconfigsstorageaccountresourceid) | string | Resource ID of the storage account to be linked. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`containers`](#parameter-storageinsightsconfigscontainers) | array | The names of the blob containers that the workspace should read. | +| [`tables`](#parameter-storageinsightsconfigstables) | array | List of tables to be read by the workspace. | + +### Parameter: `storageInsightsConfigs.storageAccountResourceId` + +Resource ID of the storage account to be linked. + +- Required: Yes +- Type: string + +### Parameter: `storageInsightsConfigs.containers` + +The names of the blob containers that the workspace should read. + +- Required: No +- Type: array + +### Parameter: `storageInsightsConfigs.tables` + +List of tables to be read by the workspace. + +- Required: No +- Type: array ### Parameter: `tables` @@ -2989,7 +3498,373 @@ LAW custom tables to be deployed. - Required: No - Type: array -- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-tablesname) | string | The name of the table. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`plan`](#parameter-tablesplan) | string | The plan for the table. | +| [`restoredLogs`](#parameter-tablesrestoredlogs) | object | The restored logs for the table. | +| [`retentionInDays`](#parameter-tablesretentionindays) | int | The retention in days for the table. | +| [`roleAssignments`](#parameter-tablesroleassignments) | array | The role assignments for the table. | +| [`schema`](#parameter-tablesschema) | object | The schema for the table. | +| [`searchResults`](#parameter-tablessearchresults) | object | The search results for the table. | +| [`totalRetentionInDays`](#parameter-tablestotalretentionindays) | int | The total retention in days for the table. | + +### Parameter: `tables.name` + +The name of the table. + +- Required: Yes +- Type: string + +### Parameter: `tables.plan` + +The plan for the table. + +- Required: No +- Type: string + +### Parameter: `tables.restoredLogs` + +The restored logs for the table. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`endRestoreTime`](#parameter-tablesrestoredlogsendrestoretime) | string | The timestamp to end the restore by (UTC). | +| [`sourceTable`](#parameter-tablesrestoredlogssourcetable) | string | The table to restore data from. | +| [`startRestoreTime`](#parameter-tablesrestoredlogsstartrestoretime) | string | The timestamp to start the restore from (UTC). | + +### Parameter: `tables.restoredLogs.endRestoreTime` + +The timestamp to end the restore by (UTC). + +- Required: No +- Type: string + +### Parameter: `tables.restoredLogs.sourceTable` + +The table to restore data from. + +- Required: No +- Type: string + +### Parameter: `tables.restoredLogs.startRestoreTime` + +The timestamp to start the restore from (UTC). + +- Required: No +- Type: string + +### Parameter: `tables.retentionInDays` + +The retention in days for the table. + +- Required: No +- Type: int + +### Parameter: `tables.roleAssignments` + +The role assignments for the table. + +- Required: No +- Type: array +- Roles configurable by name: + - `'Contributor'` + - `'Log Analytics Contributor'` + - `'Log Analytics Reader'` + - `'Monitoring Contributor'` + - `'Monitoring Reader'` + - `'Owner'` + - `'Reader'` + - `'Role Based Access Control Administrator'` + - `'User Access Administrator'` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-tablesroleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-tablesroleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-tablesroleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-tablesroleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-tablesroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-tablesroleassignmentsdescription) | string | The description of the role assignment. | +| [`name`](#parameter-tablesroleassignmentsname) | string | The name (as GUID) of the role assignment. If not provided, a GUID will be generated. | +| [`principalType`](#parameter-tablesroleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `tables.roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `tables.roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `tables.roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `tables.roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `tables.roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `tables.roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `tables.roleAssignments.name` + +The name (as GUID) of the role assignment. If not provided, a GUID will be generated. + +- Required: No +- Type: string + +### Parameter: `tables.roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `tables.schema` + +The schema for the table. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`columns`](#parameter-tablesschemacolumns) | array | A list of table custom columns. | +| [`name`](#parameter-tablesschemaname) | string | The table name. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-tablesschemadescription) | string | The table description. | +| [`displayName`](#parameter-tablesschemadisplayname) | string | The table display name. | + +### Parameter: `tables.schema.columns` + +A list of table custom columns. + +- Required: Yes +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-tablesschemacolumnsname) | string | The column name. | +| [`type`](#parameter-tablesschemacolumnstype) | string | The column type. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`dataTypeHint`](#parameter-tablesschemacolumnsdatatypehint) | string | The column data type logical hint. | +| [`description`](#parameter-tablesschemacolumnsdescription) | string | The column description. | +| [`displayName`](#parameter-tablesschemacolumnsdisplayname) | string | Column display name. | + +### Parameter: `tables.schema.columns.name` + +The column name. + +- Required: Yes +- Type: string + +### Parameter: `tables.schema.columns.type` + +The column type. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'boolean' + 'dateTime' + 'dynamic' + 'guid' + 'int' + 'long' + 'real' + 'string' + ] + ``` + +### Parameter: `tables.schema.columns.dataTypeHint` + +The column data type logical hint. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'armPath' + 'guid' + 'ip' + 'uri' + ] + ``` + +### Parameter: `tables.schema.columns.description` + +The column description. + +- Required: No +- Type: string + +### Parameter: `tables.schema.columns.displayName` + +Column display name. + +- Required: No +- Type: string + +### Parameter: `tables.schema.name` + +The table name. + +- Required: Yes +- Type: string + +### Parameter: `tables.schema.description` + +The table description. + +- Required: No +- Type: string + +### Parameter: `tables.schema.displayName` + +The table display name. + +- Required: No +- Type: string + +### Parameter: `tables.searchResults` + +The search results for the table. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`query`](#parameter-tablessearchresultsquery) | string | The search job query. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-tablessearchresultsdescription) | string | The search description. | +| [`endSearchTime`](#parameter-tablessearchresultsendsearchtime) | string | The timestamp to end the search by (UTC). | +| [`limit`](#parameter-tablessearchresultslimit) | int | Limit the search job to return up to specified number of rows. | +| [`startSearchTime`](#parameter-tablessearchresultsstartsearchtime) | string | The timestamp to start the search from (UTC). | + +### Parameter: `tables.searchResults.query` + +The search job query. + +- Required: Yes +- Type: string + +### Parameter: `tables.searchResults.description` + +The search description. + +- Required: No +- Type: string + +### Parameter: `tables.searchResults.endSearchTime` + +The timestamp to end the search by (UTC). + +- Required: No +- Type: string + +### Parameter: `tables.searchResults.limit` + +Limit the search job to return up to specified number of rows. + +- Required: No +- Type: int + +### Parameter: `tables.searchResults.startSearchTime` + +The timestamp to start the search from (UTC). + +- Required: No +- Type: string + +### Parameter: `tables.totalRetentionInDays` + +The total retention in days for the table. + +- Required: No +- Type: int ### Parameter: `tags` @@ -3023,7 +3898,8 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/operations-management/solution:0.1.0` | Remote reference | +| `br/public:avm/res/operations-management/solution:0.3.0` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/operational-insights/workspace/data-export/README.md b/avm/res/operational-insights/workspace/data-export/README.md index dfaf353e3c..c4bbb39e28 100644 --- a/avm/res/operational-insights/workspace/data-export/README.md +++ b/avm/res/operational-insights/workspace/data-export/README.md @@ -21,6 +21,7 @@ This module deploys a Log Analytics Workspace Data Export. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | The data export rule name. | +| [`tableNames`](#parameter-tablenames) | array | An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']. | **Conditional parameters** @@ -34,7 +35,6 @@ This module deploys a Log Analytics Workspace Data Export. | :-- | :-- | :-- | | [`destination`](#parameter-destination) | object | Destination properties. | | [`enable`](#parameter-enable) | bool | Active when enabled. | -| [`tableNames`](#parameter-tablenames) | array | An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']. | ### Parameter: `name` @@ -43,6 +43,13 @@ The data export rule name. - Required: Yes - Type: string +### Parameter: `tableNames` + +An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']. + +- Required: Yes +- Type: array + ### Parameter: `workspaceName` The name of the parent workspaces. Required if the template is used in a standalone deployment. @@ -56,23 +63,53 @@ Destination properties. - Required: No - Type: object -- Default: `{}` -### Parameter: `enable` +**Required parameters** -Active when enabled. +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`resourceId`](#parameter-destinationresourceid) | string | The destination resource ID. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`metaData`](#parameter-destinationmetadata) | object | The destination metadata. | + +### Parameter: `destination.resourceId` + +The destination resource ID. + +- Required: Yes +- Type: string + +### Parameter: `destination.metaData` + +The destination metadata. - Required: No -- Type: bool -- Default: `False` +- Type: object -### Parameter: `tableNames` +**Optional parameters** -An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']. +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`eventHubName`](#parameter-destinationmetadataeventhubname) | string | Allows to define an Event Hub name. Not applicable when destination is Storage Account. | + +### Parameter: `destination.metaData.eventHubName` + +Allows to define an Event Hub name. Not applicable when destination is Storage Account. - Required: No -- Type: array -- Default: `[]` +- Type: string + +### Parameter: `enable` + +Active when enabled. + +- Required: No +- Type: bool +- Default: `False` ## Outputs diff --git a/avm/res/operational-insights/workspace/data-export/main.bicep b/avm/res/operational-insights/workspace/data-export/main.bicep index f0d631fd74..16e76d5f78 100644 --- a/avm/res/operational-insights/workspace/data-export/main.bicep +++ b/avm/res/operational-insights/workspace/data-export/main.bicep @@ -15,13 +15,14 @@ param name string param workspaceName string @description('Optional. Destination properties.') -param destination object = {} +param destination destinationType? @description('Optional. Active when enabled.') param enable bool = false -@description('Optional. An array of tables to export, for example: [\'Heartbeat\', \'SecurityEvent\'].') -param tableNames array = [] +@minLength(1) +@description('Required. An array of tables to export, for example: [\'Heartbeat\', \'SecurityEvent\'].') +param tableNames string[] // =============== // // Deployments // @@ -53,3 +54,19 @@ output resourceId string = dataExport.id @description('The name of the resource group the data export was created in.') output resourceGroupName string = resourceGroup().name + +// =============== // +// Definitions // +// =============== // + +@export() +@description('The data export destination properties.') +type destinationType = { + @description('Required. The destination resource ID.') + resourceId: string + @description('Optional. The destination metadata.') + metaData: { + @description('Optional. Allows to define an Event Hub name. Not applicable when destination is Storage Account.') + eventHubName: string? + }? +} diff --git a/avm/res/operational-insights/workspace/data-export/main.json b/avm/res/operational-insights/workspace/data-export/main.json index 93d4ebbfff..e7827b942f 100644 --- a/avm/res/operational-insights/workspace/data-export/main.json +++ b/avm/res/operational-insights/workspace/data-export/main.json @@ -1,16 +1,50 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5765609820817623497" + "version": "0.31.92.45157", + "templateHash": "8392467222383128491" }, "name": "Log Analytics Workspace Data Exports", "description": "This module deploys a Log Analytics Workspace Data Export.", "owner": "Azure/module-maintainers" }, + "definitions": { + "destinationType": { + "type": "object", + "properties": { + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The destination resource ID." + } + }, + "metaData": { + "type": "object", + "properties": { + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Allows to define an Event Hub name. Not applicable when destination is Storage Account." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The destination metadata." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The data export destination properties." + } + } + }, "parameters": { "name": { "type": "string", @@ -27,8 +61,8 @@ } }, "destination": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/destinationType", + "nullable": true, "metadata": { "description": "Optional. Destination properties." } @@ -42,14 +76,23 @@ }, "tableNames": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "minLength": 1, "metadata": { - "description": "Optional. An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']." + "description": "Required. An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']." } } }, - "resources": [ - { + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('workspaceName')]" + }, + "dataExport": { "type": "Microsoft.OperationalInsights/workspaces/dataExports", "apiVersion": "2020-08-01", "name": "[format('{0}/{1}', parameters('workspaceName'), parameters('name'))]", @@ -57,9 +100,12 @@ "destination": "[parameters('destination')]", "enable": "[parameters('enable')]", "tableNames": "[parameters('tableNames')]" - } + }, + "dependsOn": [ + "workspace" + ] } - ], + }, "outputs": { "name": { "type": "string", diff --git a/avm/res/operational-insights/workspace/data-source/README.md b/avm/res/operational-insights/workspace/data-source/README.md index 9bd1009d80..752f4583a9 100644 --- a/avm/res/operational-insights/workspace/data-source/README.md +++ b/avm/res/operational-insights/workspace/data-source/README.md @@ -20,8 +20,7 @@ This module deploys a Log Analytics Workspace Data Source. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`kind`](#parameter-kind) | string | The kind of the DataSource. | -| [`name`](#parameter-name) | string | Name of the solution. | +| [`name`](#parameter-name) | string | Name of the data source. | **Conditional parameters** @@ -38,6 +37,7 @@ This module deploys a Log Analytics Workspace Data Source. | [`eventTypes`](#parameter-eventtypes) | array | Windows event types to configure when kind is WindowsEvent. | | [`instanceName`](#parameter-instancename) | string | Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | | [`intervalSeconds`](#parameter-intervalseconds) | int | Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| [`kind`](#parameter-kind) | string | The kind of the data source. | | [`linkedResourceId`](#parameter-linkedresourceid) | string | Resource ID of the resource to be linked. | | [`objectName`](#parameter-objectname) | string | Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | | [`performanceCounters`](#parameter-performancecounters) | array | List of counters to configure when the kind is LinuxPerformanceObject. | @@ -46,30 +46,9 @@ This module deploys a Log Analytics Workspace Data Source. | [`syslogSeverities`](#parameter-syslogseverities) | array | Severities to configure when kind is LinuxSyslog. | | [`tags`](#parameter-tags) | object | Tags to configure in the resource. | -### Parameter: `kind` - -The kind of the DataSource. - -- Required: No -- Type: string -- Default: `'AzureActivityLog'` -- Allowed: - ```Bicep - [ - 'AzureActivityLog' - 'IISLogs' - 'LinuxPerformanceCollection' - 'LinuxPerformanceObject' - 'LinuxSyslog' - 'LinuxSyslogCollection' - 'WindowsEvent' - 'WindowsPerformanceCounter' - ] - ``` - ### Parameter: `name` -Name of the solution. +Name of the data source. - Required: Yes - Type: string @@ -87,7 +66,6 @@ Counter name to configure when kind is WindowsPerformanceCounter. - Required: No - Type: string -- Default: `''` ### Parameter: `eventLogName` @@ -95,7 +73,6 @@ Windows event log name to configure when kind is WindowsEvent. - Required: No - Type: string -- Default: `''` ### Parameter: `eventTypes` @@ -121,13 +98,33 @@ Interval in seconds to configure when kind is WindowsPerformanceCounter or Linux - Type: int - Default: `60` +### Parameter: `kind` + +The kind of the data source. + +- Required: No +- Type: string +- Default: `'AzureActivityLog'` +- Allowed: + ```Bicep + [ + 'AzureActivityLog' + 'IISLogs' + 'LinuxPerformanceCollection' + 'LinuxPerformanceObject' + 'LinuxSyslog' + 'LinuxSyslogCollection' + 'WindowsEvent' + 'WindowsPerformanceCounter' + ] + ``` + ### Parameter: `linkedResourceId` Resource ID of the resource to be linked. - Required: No - Type: string -- Default: `''` ### Parameter: `objectName` @@ -135,7 +132,6 @@ Name of the object to configure when kind is WindowsPerformanceCounter or LinuxP - Required: No - Type: string -- Default: `''` ### Parameter: `performanceCounters` @@ -151,7 +147,6 @@ State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerform - Required: No - Type: string -- Default: `''` ### Parameter: `syslogName` @@ -159,7 +154,6 @@ System log to configure when kind is LinuxSyslog. - Required: No - Type: string -- Default: `''` ### Parameter: `syslogSeverities` diff --git a/avm/res/operational-insights/workspace/data-source/main.bicep b/avm/res/operational-insights/workspace/data-source/main.bicep index 905ff55e0e..9b74a191a6 100644 --- a/avm/res/operational-insights/workspace/data-source/main.bicep +++ b/avm/res/operational-insights/workspace/data-source/main.bicep @@ -5,10 +5,10 @@ metadata owner = 'Azure/module-maintainers' @description('Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment.') param logAnalyticsWorkspaceName string -@description('Required. Name of the solution.') +@description('Required. Name of the data source.') param name string -@description('Required. The kind of the DataSource.') +@description('Optional. The kind of the data source.') @allowed([ 'AzureActivityLog' 'WindowsEvent' @@ -25,16 +25,16 @@ param kind string = 'AzureActivityLog' param tags object? @description('Optional. Resource ID of the resource to be linked.') -param linkedResourceId string = '' +param linkedResourceId string? @description('Optional. Windows event log name to configure when kind is WindowsEvent.') -param eventLogName string = '' +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 = '' +param objectName string? @description('Optional. Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') param instanceName string = '*' @@ -46,13 +46,13 @@ param intervalSeconds int = 60 param performanceCounters array = [] @description('Optional. Counter name to configure when kind is WindowsPerformanceCounter.') -param counterName string = '' +param counterName string? @description('Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection.') -param state string = '' +param state string? @description('Optional. System log to configure when kind is LinuxSyslog.') -param syslogName string = '' +param syslogName string? @description('Optional. Severities to configure when kind is LinuxSyslog.') param syslogSeverities array = [] diff --git a/avm/res/operational-insights/workspace/data-source/main.json b/avm/res/operational-insights/workspace/data-source/main.json index 947d1fb8c0..6e154c67ac 100644 --- a/avm/res/operational-insights/workspace/data-source/main.json +++ b/avm/res/operational-insights/workspace/data-source/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13460038983765020046" + "version": "0.31.92.45157", + "templateHash": "3019400626196043317" }, "name": "Log Analytics Workspace Datasources", "description": "This module deploys a Log Analytics Workspace Data Source.", @@ -22,7 +22,7 @@ "name": { "type": "string", "metadata": { - "description": "Required. Name of the solution." + "description": "Required. Name of the data source." } }, "kind": { @@ -39,7 +39,7 @@ "LinuxPerformanceCollection" ], "metadata": { - "description": "Required. The kind of the DataSource." + "description": "Optional. The kind of the data source." } }, "tags": { @@ -51,14 +51,14 @@ }, "linkedResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Resource ID of the resource to be linked." } }, "eventLogName": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Windows event log name to configure when kind is WindowsEvent." } @@ -72,7 +72,7 @@ }, "objectName": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." } @@ -100,21 +100,21 @@ }, "counterName": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Counter name to configure when kind is WindowsPerformanceCounter." } }, "state": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection." } }, "syslogName": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. System log to configure when kind is LinuxSyslog." } diff --git a/avm/res/operational-insights/workspace/linked-service/README.md b/avm/res/operational-insights/workspace/linked-service/README.md index 4ee91e39ec..bca53b7a24 100644 --- a/avm/res/operational-insights/workspace/linked-service/README.md +++ b/avm/res/operational-insights/workspace/linked-service/README.md @@ -21,7 +21,6 @@ This module deploys a Log Analytics Workspace Linked Service. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | Name of the link. | -| [`resourceId`](#parameter-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. | **Conditional parameters** @@ -33,6 +32,7 @@ This module deploys a Log Analytics Workspace Linked Service. | Parameter | Type | Description | | :-- | :-- | :-- | +| [`resourceId`](#parameter-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. | | [`tags`](#parameter-tags) | object | Tags to configure in the resource. | | [`writeAccessResourceId`](#parameter-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. | @@ -43,19 +43,18 @@ Name of the link. - Required: Yes - Type: string -### Parameter: `resourceId` +### Parameter: `logAnalyticsWorkspaceName` -The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access. +The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment. -- Required: No +- Required: Yes - Type: string -- Default: `''` -### Parameter: `logAnalyticsWorkspaceName` +### Parameter: `resourceId` -The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment. +The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access. -- Required: Yes +- Required: No - Type: string ### Parameter: `tags` @@ -71,7 +70,6 @@ The resource ID of the resource that will be linked to the workspace. This shoul - Required: No - Type: string -- Default: `''` ## Outputs diff --git a/avm/res/operational-insights/workspace/linked-service/main.bicep b/avm/res/operational-insights/workspace/linked-service/main.bicep index ffe1bc4c99..8a35e22e57 100644 --- a/avm/res/operational-insights/workspace/linked-service/main.bicep +++ b/avm/res/operational-insights/workspace/linked-service/main.bicep @@ -8,11 +8,11 @@ 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 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 = '' +param writeAccessResourceId string? @description('Optional. Tags to configure in the resource.') param tags object? @@ -27,7 +27,7 @@ resource linkedService 'Microsoft.OperationalInsights/workspaces/linkedServices@ tags: tags properties: { resourceId: resourceId - writeAccessResourceId: empty(writeAccessResourceId) ? null : writeAccessResourceId + writeAccessResourceId: writeAccessResourceId } } diff --git a/avm/res/operational-insights/workspace/linked-service/main.json b/avm/res/operational-insights/workspace/linked-service/main.json index 7235c7ef1b..b4305d5972 100644 --- a/avm/res/operational-insights/workspace/linked-service/main.json +++ b/avm/res/operational-insights/workspace/linked-service/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12032441371027552374" + "version": "0.31.92.45157", + "templateHash": "815879010072595898" }, "name": "Log Analytics Workspace Linked Services", "description": "This module deploys a Log Analytics Workspace Linked Service.", @@ -27,14 +27,14 @@ }, "resourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { - "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." + "description": "Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access." } }, "writeAccessResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "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." } @@ -61,7 +61,7 @@ "tags": "[parameters('tags')]", "properties": { "resourceId": "[parameters('resourceId')]", - "writeAccessResourceId": "[if(empty(parameters('writeAccessResourceId')), null(), parameters('writeAccessResourceId'))]" + "writeAccessResourceId": "[parameters('writeAccessResourceId')]" }, "dependsOn": [ "workspace" diff --git a/avm/res/operational-insights/workspace/linked-storage-account/README.md b/avm/res/operational-insights/workspace/linked-storage-account/README.md index 40e1029831..a4604fdeea 100644 --- a/avm/res/operational-insights/workspace/linked-storage-account/README.md +++ b/avm/res/operational-insights/workspace/linked-storage-account/README.md @@ -21,7 +21,7 @@ This module deploys a Log Analytics Workspace Linked Storage Account. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | Name of the link. | -| [`resourceId`](#parameter-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. | +| [`storageAccountIds`](#parameter-storageaccountids) | array | Linked storage accounts resources Ids. | **Conditional parameters** @@ -45,12 +45,12 @@ Name of the link. ] ``` -### Parameter: `resourceId` +### Parameter: `storageAccountIds` -The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access. +Linked storage accounts resources Ids. - Required: Yes -- Type: string +- Type: array ### Parameter: `logAnalyticsWorkspaceName` diff --git a/avm/res/operational-insights/workspace/linked-storage-account/main.bicep b/avm/res/operational-insights/workspace/linked-storage-account/main.bicep index 60ec0f85d8..4107bc9470 100644 --- a/avm/res/operational-insights/workspace/linked-storage-account/main.bicep +++ b/avm/res/operational-insights/workspace/linked-storage-account/main.bicep @@ -14,8 +14,9 @@ param logAnalyticsWorkspaceName string ]) 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 +@minLength(1) +@description('Required. Linked storage accounts resources Ids.') +param storageAccountIds string[] resource workspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = { name: logAnalyticsWorkspaceName @@ -25,9 +26,7 @@ resource linkedStorageAccount 'Microsoft.OperationalInsights/workspaces/linkedSt name: name parent: workspace properties: { - storageAccountIds: [ - resourceId - ] + storageAccountIds: storageAccountIds } } diff --git a/avm/res/operational-insights/workspace/linked-storage-account/main.json b/avm/res/operational-insights/workspace/linked-storage-account/main.json index 7c3b81ed2d..8e76c78f95 100644 --- a/avm/res/operational-insights/workspace/linked-storage-account/main.json +++ b/avm/res/operational-insights/workspace/linked-storage-account/main.json @@ -1,11 +1,12 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12623216644328477682" + "version": "0.31.92.45157", + "templateHash": "15129623170213660788" }, "name": "Log Analytics Workspace Linked Storage Accounts", "description": "This module deploys a Log Analytics Workspace Linked Storage Account.", @@ -30,25 +31,36 @@ "description": "Required. Name of the link." } }, - "resourceId": { - "type": "string", + "storageAccountIds": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, "metadata": { - "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." + "description": "Required. Linked storage accounts resources Ids." } } }, - "resources": [ - { + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "linkedStorageAccount": { "type": "Microsoft.OperationalInsights/workspaces/linkedStorageAccounts", "apiVersion": "2020-08-01", "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", "properties": { - "storageAccountIds": [ - "[parameters('resourceId')]" - ] - } + "storageAccountIds": "[parameters('storageAccountIds')]" + }, + "dependsOn": [ + "workspace" + ] } - ], + }, "outputs": { "name": { "type": "string", diff --git a/avm/res/operational-insights/workspace/main.bicep b/avm/res/operational-insights/workspace/main.bicep index b5be253202..94542a2860 100644 --- a/avm/res/operational-insights/workspace/main.bicep +++ b/avm/res/operational-insights/workspace/main.bicep @@ -27,28 +27,31 @@ param skuName string = 'PerGB2018' param skuCapacityReservationLevel int = 100 @description('Optional. List of storage accounts to be read by the workspace.') -param storageInsightsConfigs array = [] +param storageInsightsConfigs storageInsightsConfigType[]? @description('Optional. List of services to be linked.') -param linkedServices array = [] +param linkedServices linkedServiceType[]? @description('Conditional. List of Storage Accounts to be linked. Required if \'forceCmkForQuery\' is set to \'true\' and \'savedSearches\' is not empty.') -param linkedStorageAccounts array = [] +param linkedStorageAccounts linkedStorageAccountType[]? @description('Optional. Kusto Query Language searches to save.') -param savedSearches array = [] +param savedSearches savedSearchType[]? @description('Optional. LAW data export instances to be deployed.') -param dataExports array = [] +param dataExports dataExportType[]? @description('Optional. LAW data sources to configure.') -param dataSources array = [] +param dataSources dataSourceType[]? @description('Optional. LAW custom tables to be deployed.') -param tables array = [] +param tables tableType[]? @description('Optional. List of gallerySolutions to be created in the log analytics workspace.') -param gallerySolutions array = [] +param gallerySolutions gallerySolutionType[]? + +@description('Optional. Onboard the Log Analytics Workspace to Sentinel. Requires \'SecurityInsights\' solution to be in gallerySolutions.') +param onboardWorkspaceToSentinel bool = false @description('Optional. Number of days data will be retained for.') @minValue(0) @@ -73,23 +76,26 @@ param publicNetworkAccessForIngestion string = 'Enabled' ]) param publicNetworkAccessForQuery string = 'Enabled' +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityAllType? @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. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingType[]? @description('Optional. Indicates whether customer managed storage is mandatory for query management.') param forceCmkForQuery bool = true +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the resource.') param tags object? @@ -236,7 +242,7 @@ resource logAnalyticsWorkspace_diagnosticSettings 'Microsoft.Insights/diagnostic ] module logAnalyticsWorkspace_storageInsightConfigs 'storage-insight-config/main.bicep' = [ - for (storageInsightsConfig, index) in storageInsightsConfigs: { + for (storageInsightsConfig, index) in storageInsightsConfigs ?? []: { name: '${uniqueString(deployment().name, location)}-LAW-StorageInsightsConfig-${index}' params: { logAnalyticsWorkspaceName: logAnalyticsWorkspace.name @@ -248,7 +254,7 @@ module logAnalyticsWorkspace_storageInsightConfigs 'storage-insight-config/main. ] module logAnalyticsWorkspace_linkedServices 'linked-service/main.bicep' = [ - for (linkedService, index) in linkedServices: { + for (linkedService, index) in linkedServices ?? []: { name: '${uniqueString(deployment().name, location)}-LAW-LinkedService-${index}' params: { logAnalyticsWorkspaceName: logAnalyticsWorkspace.name @@ -260,18 +266,18 @@ module logAnalyticsWorkspace_linkedServices 'linked-service/main.bicep' = [ ] module logAnalyticsWorkspace_linkedStorageAccounts 'linked-storage-account/main.bicep' = [ - for (linkedStorageAccount, index) in linkedStorageAccounts: { + for (linkedStorageAccount, index) in linkedStorageAccounts ?? []: { name: '${uniqueString(deployment().name, location)}-LAW-LinkedStorageAccount-${index}' params: { logAnalyticsWorkspaceName: logAnalyticsWorkspace.name name: linkedStorageAccount.name - resourceId: linkedStorageAccount.resourceId + storageAccountIds: linkedStorageAccount.storageAccountIds } } ] module logAnalyticsWorkspace_savedSearches 'saved-search/main.bicep' = [ - for (savedSearch, index) in savedSearches: { + for (savedSearch, index) in savedSearches ?? []: { name: '${uniqueString(deployment().name, location)}-LAW-SavedSearch-${index}' params: { logAnalyticsWorkspaceName: logAnalyticsWorkspace.name @@ -282,6 +288,7 @@ module logAnalyticsWorkspace_savedSearches 'saved-search/main.bicep' = [ query: savedSearch.query functionAlias: savedSearch.?functionAlias functionParameters: savedSearch.?functionParameters + tags: savedSearch.?tags version: savedSearch.?version } dependsOn: [ @@ -291,7 +298,7 @@ module logAnalyticsWorkspace_savedSearches 'saved-search/main.bicep' = [ ] module logAnalyticsWorkspace_dataExports 'data-export/main.bicep' = [ - for (dataExport, index) in dataExports: { + for (dataExport, index) in dataExports ?? []: { name: '${uniqueString(deployment().name, location)}-LAW-DataExport-${index}' params: { workspaceName: logAnalyticsWorkspace.name @@ -304,7 +311,7 @@ module logAnalyticsWorkspace_dataExports 'data-export/main.bicep' = [ ] module logAnalyticsWorkspace_dataSources 'data-source/main.bicep' = [ - for (dataSource, index) in dataSources: { + for (dataSource, index) in dataSources ?? []: { name: '${uniqueString(deployment().name, location)}-LAW-DataSource-${index}' params: { logAnalyticsWorkspaceName: logAnalyticsWorkspace.name @@ -321,12 +328,13 @@ module logAnalyticsWorkspace_dataSources 'data-source/main.bicep' = [ syslogName: dataSource.?syslogName syslogSeverities: dataSource.?syslogSeverities performanceCounters: dataSource.?performanceCounters + tags: dataSource.?tags } } ] module logAnalyticsWorkspace_tables 'table/main.bicep' = [ - for (table, index) in tables: { + for (table, index) in tables ?? []: { name: '${uniqueString(deployment().name, location)}-LAW-Table-${index}' params: { workspaceName: logAnalyticsWorkspace.name @@ -342,20 +350,29 @@ module logAnalyticsWorkspace_tables 'table/main.bicep' = [ } ] -module logAnalyticsWorkspace_solutions 'br/public:avm/res/operations-management/solution:0.1.0' = [ - for (gallerySolution, index) in gallerySolutions: if (!empty(gallerySolutions)) { +module logAnalyticsWorkspace_solutions 'br/public:avm/res/operations-management/solution:0.3.0' = [ + for (gallerySolution, index) in gallerySolutions ?? []: if (!empty(gallerySolutions)) { name: '${uniqueString(deployment().name, location)}-LAW-Solution-${index}' params: { name: gallerySolution.name location: location logAnalyticsWorkspaceName: logAnalyticsWorkspace.name - product: gallerySolution.?product - publisher: gallerySolution.?publisher + plan: gallerySolution.plan enableTelemetry: gallerySolution.?enableTelemetry ?? enableTelemetry } } ] +// Onboard the Log Analytics Workspace to Sentinel if SecurityInsights is in gallerySolutions and onboardWorkspaceToSentinel is set to true +resource logAnalyticsWorkspace_sentinelOnboarding 'Microsoft.SecurityInsights/onboardingStates@2024-03-01' = if (!empty(filter( + gallerySolutions ?? [], + item => startsWith(item.name, 'SecurityInsights') +)) && onboardWorkspaceToSentinel) { + name: 'default' + scope: logAnalyticsWorkspace + properties: {} +} + resource logAnalyticsWorkspace_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { name: lock.?name ?? 'lock-${name}' properties: { @@ -409,48 +426,6 @@ output systemAssignedMIPrincipalId string = logAnalyticsWorkspace.?identity.?pri // Definitions // // =============== // -type managedIdentitiesType = { - @description('Optional. Enables system assigned managed identity on the resource.') - systemAssigned: bool? - - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[]? -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - type diagnosticSettingType = { @description('Optional. The name of diagnostic setting.') name: string? @@ -496,4 +471,181 @@ type diagnosticSettingType = { @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') marketplacePartnerResourceId: string? -}[]? +} + +import { solutionPlanType } from 'br/public:avm/res/operations-management/solution:0.3.0' + +@export() +@description('Properties of the gallery solutions to be created in the log analytics workspace.') +type gallerySolutionType = { + @description('''Required. Name of the solution. + For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`. + For solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`. + The solution type is case-sensitive.''') + name: string + + @description('Required. Plan for solution object supported by the OperationsManagement resource provider.') + plan: solutionPlanType +} + +@export() +@description('Properties of the storage insights configuration.') +type storageInsightsConfigType = { + @description('Required. Resource ID of the storage account to be linked.') + storageAccountResourceId: string + + @description('Optional. The names of the blob containers that the workspace should read.') + containers: string[]? + + @description('Optional. List of tables to be read by the workspace.') + tables: string[]? +} + +@export() +@description('Properties of the linked service.') +type linkedServiceType = { + @description('Required. Name of the linked service.') + name: 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 read access.') + 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.') + writeAccessResourceId: string? +} + +@export() +@description('Properties of the linked storage account.') +type linkedStorageAccountType = { + @description('Required. Name of the link.') + name: string + + @minLength(1) + @description('Required. Linked storage accounts resources Ids.') + storageAccountIds: string[] +} + +@export() +@description('Properties of the saved search.') +type savedSearchType = { + @description('Required. Name of the saved search.') + name: string + + @description('Optional. The ETag of the saved search. To override an existing saved search, use "*" or specify the current Etag.') + etag: string? + + @description('Required. The category of the saved search. This helps the user to find a saved search faster.') + category: string + + @description('Required. Display name for the search.') + displayName: string + + @description('Optional. The function alias if query serves as a function.') + 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.') + functionParameters: string? + + @description('Required. The query expression for the saved search.') + query: string + + @description('Optional. The tags attached to the saved search.') + tags: array? + + @description('Optional. The version number of the query language. The current version is 2 and is the default.') + version: int? +} + +import { destinationType } from 'data-export/main.bicep' + +@export() +@description('Properties of the data export.') +type dataExportType = { + @description('Required. Name of the data export.') + name: string + + @description('Optional. The destination of the data export.') + destination: destinationType? + + @description('Optional. Enable or disable the data export.') + enable: bool? + + @description('Required. The list of table names to export.') + tableNames: string[] +} + +@export() +@description('Properties of the data source.') +type dataSourceType = { + @description('Required. Name of the data source.') + name: string + + @description('Required. The kind of data source.') + kind: string + + @description('Optional. The resource id of the resource that will be linked to the workspace.') + linkedResourceId: string? + + @description('Optional. The name of the event log to configure when kind is WindowsEvent.') + eventLogName: string? + + @description('Optional. The event types to configure when kind is WindowsEvent.') + eventTypes: array? + + @description('Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') + objectName: string? + + @description('Optional. Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') + instanceName: string? + + @description('Optional. Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') + intervalSeconds: int? + + @description('Optional. List of counters to configure when the kind is LinuxPerformanceObject.') + performanceCounters: array? + + @description('Optional. Counter name to configure when kind is WindowsPerformanceCounter.') + counterName: string? + + @description('Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection.') + state: string? + + @description('Optional. System log to configure when kind is LinuxSyslog.') + syslogName: string? + + @description('Optional. Severities to configure when kind is LinuxSyslog.') + syslogSeverities: array? + + @description('Optional. Tags to configure in the resource.') + tags: object? +} + +import { schemaType, restoredLogsType, searchResultsType } from 'table/main.bicep' + +@export() +@description('Properties of the custom table.') +type tableType = { + @description('Required. The name of the table.') + name: string + + @description('Optional. The plan for the table.') + plan: string? + + @description('Optional. The restored logs for the table.') + restoredLogs: restoredLogsType? + + @description('Optional. The schema for the table.') + schema: schemaType? + + @description('Optional. The search results for the table.') + searchResults: searchResultsType? + + @description('Optional. The retention in days for the table.') + retentionInDays: int? + + @description('Optional. The total retention in days for the table.') + totalRetentionInDays: int? + + @description('Optional. The role assignments for the table.') + roleAssignments: roleAssignmentType[]? +} diff --git a/avm/res/operational-insights/workspace/main.json b/avm/res/operational-insights/workspace/main.json index 61d489e40d..5af1767572 100644 --- a/avm/res/operational-insights/workspace/main.json +++ b/avm/res/operational-insights/workspace/main.json @@ -5,261 +5,897 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15059379956726052447" + "version": "0.31.92.45157", + "templateHash": "4016402011070477200" }, "name": "Log Analytics Workspaces", "description": "This module deploys a Log Analytics Workspace.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { + "diagnosticSettingType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "useThisWorkspace": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Instead of using an external reference, use the deployed instance as the target for its diagnostic settings. If set to `true`, the `workspaceResourceId` property is ignored." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "gallerySolutionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the solution.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.\nThe solution type is case-sensitive." + } + }, + "plan": { + "$ref": "#/definitions/solutionPlanType", + "metadata": { + "description": "Required. Plan for solution object supported by the OperationsManagement resource provider." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "Properties of the gallery solutions to be created in the log analytics workspace." + } + }, + "storageInsightsConfigType": { + "type": "object", + "properties": { + "storageAccountResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the storage account to be linked." + } + }, + "containers": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the blob containers that the workspace should read." + } + }, + "tables": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. List of tables to be read by the workspace." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "Properties of the storage insights configuration." + } + }, + "linkedServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the linked service." + } + }, + "resourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource id of the resource that will be linked to the workspace. This should be used for linking resources which require read access." + } + }, + "writeAccessResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "Properties of the linked service." + } + }, + "linkedStorageAccountType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the link." + } + }, + "storageAccountIds": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, + "metadata": { + "description": "Required. Linked storage accounts resources Ids." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "Properties of the linked storage account." + } + }, + "savedSearchType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the saved search." + } + }, + "etag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The ETag of the saved search. To override an existing saved search, use \"*\" or specify the current Etag." + } + }, + "category": { + "type": "string", + "metadata": { + "description": "Required. The category of the saved search. This helps the user to find a saved search faster." + } + }, + "displayName": { + "type": "string", + "metadata": { + "description": "Required. Display name for the search." + } + }, + "functionAlias": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The function alias if query serves as a function." + } + }, + "functionParameters": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + }, + "query": { + "type": "string", + "metadata": { + "description": "Required. The query expression for the saved search." + } + }, + "tags": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The tags attached to the saved search." + } + }, + "version": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The version number of the query language. The current version is 2 and is the default." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "Properties of the saved search." + } + }, + "dataExportType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the data export." + } + }, + "destination": { + "$ref": "#/definitions/destinationType", + "nullable": true, + "metadata": { + "description": "Optional. The destination of the data export." + } + }, + "enable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the data export." + } + }, + "tableNames": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The list of table names to export." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "Properties of the data export." + } + }, + "dataSourceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the data source." + } + }, + "kind": { + "type": "string", + "metadata": { + "description": "Required. The kind of data source." + } + }, + "linkedResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource id of the resource that will be linked to the workspace." + } + }, + "eventLogName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the event log to configure when kind is WindowsEvent." + } + }, + "eventTypes": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The event types to configure when kind is WindowsEvent." + } + }, + "objectName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "instanceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "intervalSeconds": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "performanceCounters": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. List of counters to configure when the kind is LinuxPerformanceObject." + } + }, + "counterName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Counter name to configure when kind is WindowsPerformanceCounter." + } + }, + "state": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection." + } + }, + "syslogName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. System log to configure when kind is LinuxSyslog." + } + }, + "syslogSeverities": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Severities to configure when kind is LinuxSyslog." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "Properties of the data source." + } + }, + "tableType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the table." + } + }, + "plan": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The plan for the table." + } + }, + "restoredLogs": { + "$ref": "#/definitions/restoredLogsType", + "nullable": true, + "metadata": { + "description": "Optional. The restored logs for the table." + } + }, + "schema": { + "$ref": "#/definitions/schemaType", + "nullable": true, + "metadata": { + "description": "Optional. The schema for the table." + } + }, + "searchResults": { + "$ref": "#/definitions/searchResultsType", + "nullable": true, + "metadata": { + "description": "Optional. The search results for the table." + } + }, + "retentionInDays": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The retention in days for the table." + } + }, + "totalRetentionInDays": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The total retention in days for the table." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The role assignments for the table." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "Properties of the custom table." + } + }, + "_1.columnType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The column name." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "boolean", + "dateTime", + "dynamic", + "guid", + "int", + "long", + "real", + "string" + ], + "metadata": { + "description": "Required. The column type." + } + }, + "dataTypeHint": { + "type": "string", + "allowedValues": [ + "armPath", + "guid", + "ip", + "uri" + ], + "nullable": true, + "metadata": { + "description": "Optional. The column data type logical hint." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The column description." + } + }, + "displayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Column display name." + } + } + }, + "metadata": { + "description": "The parameters of the table column.", + "__bicep_imported_from!": { + "sourceTemplate": "table/main.bicep" + } + } + }, + "destinationType": { + "type": "object", + "properties": { + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The destination resource ID." + } + }, + "metaData": { + "type": "object", + "properties": { + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Allows to define an Event Hub name. Not applicable when destination is Storage Account." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The destination metadata." + } + } + }, + "metadata": { + "description": "The data export destination properties.", + "__bicep_imported_from!": { + "sourceTemplate": "data-export/main.bicep" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "managedIdentityAllType": { "type": "object", "properties": { "systemAssigned": { "type": "bool", "nullable": true, "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "restoredLogsType": { + "type": "object", + "properties": { + "sourceTable": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table to restore data from." + } + }, + "startRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the restore from (UTC)." + } + }, + "endRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the restore by (UTC)." + } + } + }, + "metadata": { + "description": "The parameters of the restore operation that initiated the table.", + "__bicep_imported_from!": { + "sourceTemplate": "table/main.bicep" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." } }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "lockType": { + "schemaType": { "type": "object", "properties": { "name": { + "type": "string", + "metadata": { + "description": "Required. The table name." + } + }, + "columns": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.columnType" + }, + "metadata": { + "description": "Required. A list of table custom columns." + } + }, + "description": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. The table description." } }, - "kind": { + "displayName": { "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Optional. The table display name." } } }, - "nullable": true + "metadata": { + "description": "The table schema.", + "__bicep_imported_from!": { + "sourceTemplate": "table/main.bicep" + } + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "searchResultsType": { + "type": "object", + "properties": { + "query": { + "type": "string", + "metadata": { + "description": "Required. The search job query." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The search description." + } + }, + "limit": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Limit the search job to return up to specified number of rows." + } + }, + "startSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the search from (UTC)." + } + }, + "endSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the search by (UTC)." } } }, - "nullable": true + "metadata": { + "description": "The parameters of the search job that initiated the table.", + "__bicep_imported_from!": { + "sourceTemplate": "table/main.bicep" + } + } }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "useThisWorkspace": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Instead of using an external reference, use the deployed instance as the target for its diagnostic settings. If set to `true`, the `workspaceResourceId` property is ignored." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "solutionPlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the solution to be created.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, it can be anything.\nThe solution type is case-sensitive.\nIf not provided, the value of the `name` parameter will be used." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product name of the deployed solution.\nFor Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.\nFor a third party solution, it can be anything.\nThis is case sensitive." + } + }, + "publisher": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/res/operations-management/solution:0.3.0" + } + } } }, "parameters": { @@ -304,60 +940,91 @@ }, "storageInsightsConfigs": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/storageInsightsConfigType" + }, + "nullable": true, "metadata": { "description": "Optional. List of storage accounts to be read by the workspace." } }, "linkedServices": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/linkedServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. List of services to be linked." } }, "linkedStorageAccounts": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/linkedStorageAccountType" + }, + "nullable": true, "metadata": { "description": "Conditional. List of Storage Accounts to be linked. Required if 'forceCmkForQuery' is set to 'true' and 'savedSearches' is not empty." } }, "savedSearches": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/savedSearchType" + }, + "nullable": true, "metadata": { "description": "Optional. Kusto Query Language searches to save." } }, "dataExports": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/dataExportType" + }, + "nullable": true, "metadata": { "description": "Optional. LAW data export instances to be deployed." } }, "dataSources": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/dataSourceType" + }, + "nullable": true, "metadata": { "description": "Optional. LAW data sources to configure." } }, "tables": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/tableType" + }, + "nullable": true, "metadata": { "description": "Optional. LAW custom tables to be deployed." } }, "gallerySolutions": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/gallerySolutionType" + }, + "nullable": true, "metadata": { "description": "Optional. List of gallerySolutions to be created in the log analytics workspace." } }, + "onboardWorkspaceToSentinel": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Onboard the Log Analytics Workspace to Sentinel. Requires 'SecurityInsights' solution to be in gallerySolutions." + } + }, "dataRetention": { "type": "int", "defaultValue": 365, @@ -398,7 +1065,8 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." } @@ -411,7 +1079,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -425,12 +1097,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -561,6 +1238,17 @@ "logAnalyticsWorkspace" ] }, + "logAnalyticsWorkspace_sentinelOnboarding": { + "condition": "[and(not(empty(filter(coalesce(parameters('gallerySolutions'), createArray()), lambda('item', startsWith(lambdaVariables('item').name, 'SecurityInsights'))))), parameters('onboardWorkspaceToSentinel'))]", + "type": "Microsoft.SecurityInsights/onboardingStates", + "apiVersion": "2024-03-01", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}', parameters('name'))]", + "name": "default", + "properties": {}, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, "logAnalyticsWorkspace_lock": { "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", "type": "Microsoft.Authorization/locks", @@ -600,7 +1288,7 @@ "logAnalyticsWorkspace_storageInsightConfigs": { "copy": { "name": "logAnalyticsWorkspace_storageInsightConfigs", - "count": "[length(parameters('storageInsightsConfigs'))]" + "count": "[length(coalesce(parameters('storageInsightsConfigs'), createArray()))]" }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -615,13 +1303,13 @@ "value": "[parameters('name')]" }, "containers": { - "value": "[tryGet(parameters('storageInsightsConfigs')[copyIndex()], 'containers')]" + "value": "[tryGet(coalesce(parameters('storageInsightsConfigs'), createArray())[copyIndex()], 'containers')]" }, "tables": { - "value": "[tryGet(parameters('storageInsightsConfigs')[copyIndex()], 'tables')]" + "value": "[tryGet(coalesce(parameters('storageInsightsConfigs'), createArray())[copyIndex()], 'tables')]" }, "storageAccountResourceId": { - "value": "[parameters('storageInsightsConfigs')[copyIndex()].storageAccountResourceId]" + "value": "[coalesce(parameters('storageInsightsConfigs'), createArray())[copyIndex()].storageAccountResourceId]" } }, "template": { @@ -631,8 +1319,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "1745671120474305926" + "version": "0.31.92.45157", + "templateHash": "156138954055342275" }, "name": "Log Analytics Workspace Storage Insight Configs", "description": "This module deploys a Log Analytics Workspace Storage Insight Config.", @@ -660,14 +1348,20 @@ }, "containers": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "nullable": true, "metadata": { "description": "Optional. The names of the blob containers that the workspace should read." } }, "tables": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "nullable": true, "metadata": { "description": "Optional. The names of the Azure tables that the workspace should read." } @@ -744,7 +1438,7 @@ "logAnalyticsWorkspace_linkedServices": { "copy": { "name": "logAnalyticsWorkspace_linkedServices", - "count": "[length(parameters('linkedServices'))]" + "count": "[length(coalesce(parameters('linkedServices'), createArray()))]" }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -759,13 +1453,13 @@ "value": "[parameters('name')]" }, "name": { - "value": "[parameters('linkedServices')[copyIndex()].name]" + "value": "[coalesce(parameters('linkedServices'), createArray())[copyIndex()].name]" }, "resourceId": { - "value": "[tryGet(parameters('linkedServices')[copyIndex()], 'resourceId')]" + "value": "[tryGet(coalesce(parameters('linkedServices'), createArray())[copyIndex()], 'resourceId')]" }, "writeAccessResourceId": { - "value": "[tryGet(parameters('linkedServices')[copyIndex()], 'writeAccessResourceId')]" + "value": "[tryGet(coalesce(parameters('linkedServices'), createArray())[copyIndex()], 'writeAccessResourceId')]" } }, "template": { @@ -775,8 +1469,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12032441371027552374" + "version": "0.31.92.45157", + "templateHash": "815879010072595898" }, "name": "Log Analytics Workspace Linked Services", "description": "This module deploys a Log Analytics Workspace Linked Service.", @@ -797,14 +1491,14 @@ }, "resourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { - "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." + "description": "Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access." } }, "writeAccessResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "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." } @@ -831,7 +1525,7 @@ "tags": "[parameters('tags')]", "properties": { "resourceId": "[parameters('resourceId')]", - "writeAccessResourceId": "[if(empty(parameters('writeAccessResourceId')), null(), parameters('writeAccessResourceId'))]" + "writeAccessResourceId": "[parameters('writeAccessResourceId')]" }, "dependsOn": [ "workspace" @@ -870,7 +1564,7 @@ "logAnalyticsWorkspace_linkedStorageAccounts": { "copy": { "name": "logAnalyticsWorkspace_linkedStorageAccounts", - "count": "[length(parameters('linkedStorageAccounts'))]" + "count": "[length(coalesce(parameters('linkedStorageAccounts'), createArray()))]" }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -885,20 +1579,21 @@ "value": "[parameters('name')]" }, "name": { - "value": "[parameters('linkedStorageAccounts')[copyIndex()].name]" + "value": "[coalesce(parameters('linkedStorageAccounts'), createArray())[copyIndex()].name]" }, - "resourceId": { - "value": "[parameters('linkedStorageAccounts')[copyIndex()].resourceId]" + "storageAccountIds": { + "value": "[coalesce(parameters('linkedStorageAccounts'), createArray())[copyIndex()].storageAccountIds]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12623216644328477682" + "version": "0.31.92.45157", + "templateHash": "15129623170213660788" }, "name": "Log Analytics Workspace Linked Storage Accounts", "description": "This module deploys a Log Analytics Workspace Linked Storage Account.", @@ -923,25 +1618,36 @@ "description": "Required. Name of the link." } }, - "resourceId": { - "type": "string", + "storageAccountIds": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, "metadata": { - "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." + "description": "Required. Linked storage accounts resources Ids." } } }, - "resources": [ - { + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "linkedStorageAccount": { "type": "Microsoft.OperationalInsights/workspaces/linkedStorageAccounts", "apiVersion": "2020-08-01", "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", "properties": { - "storageAccountIds": [ - "[parameters('resourceId')]" - ] - } + "storageAccountIds": "[parameters('storageAccountIds')]" + }, + "dependsOn": [ + "workspace" + ] } - ], + }, "outputs": { "name": { "type": "string", @@ -974,7 +1680,7 @@ "logAnalyticsWorkspace_savedSearches": { "copy": { "name": "logAnalyticsWorkspace_savedSearches", - "count": "[length(parameters('savedSearches'))]" + "count": "[length(coalesce(parameters('savedSearches'), createArray()))]" }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -989,28 +1695,31 @@ "value": "[parameters('name')]" }, "name": { - "value": "[format('{0}{1}', parameters('savedSearches')[copyIndex()].name, uniqueString(deployment().name))]" + "value": "[format('{0}{1}', coalesce(parameters('savedSearches'), createArray())[copyIndex()].name, uniqueString(deployment().name))]" }, "etag": { - "value": "[tryGet(parameters('savedSearches')[copyIndex()], 'etag')]" + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'etag')]" }, "displayName": { - "value": "[parameters('savedSearches')[copyIndex()].displayName]" + "value": "[coalesce(parameters('savedSearches'), createArray())[copyIndex()].displayName]" }, "category": { - "value": "[parameters('savedSearches')[copyIndex()].category]" + "value": "[coalesce(parameters('savedSearches'), createArray())[copyIndex()].category]" }, "query": { - "value": "[parameters('savedSearches')[copyIndex()].query]" + "value": "[coalesce(parameters('savedSearches'), createArray())[copyIndex()].query]" }, "functionAlias": { - "value": "[tryGet(parameters('savedSearches')[copyIndex()], 'functionAlias')]" + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'functionAlias')]" }, "functionParameters": { - "value": "[tryGet(parameters('savedSearches')[copyIndex()], 'functionParameters')]" + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'functionParameters')]" + }, + "tags": { + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'tags')]" }, "version": { - "value": "[tryGet(parameters('savedSearches')[copyIndex()], 'version')]" + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'version')]" } }, "template": { @@ -1020,8 +1729,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7683333179440464721" + "version": "0.31.92.45157", + "templateHash": "15600200446151630277" }, "name": "Log Analytics Workspace Saved Searches", "description": "This module deploys a Log Analytics Workspace Saved Search.", @@ -1153,7 +1862,7 @@ "logAnalyticsWorkspace_dataExports": { "copy": { "name": "logAnalyticsWorkspace_dataExports", - "count": "[length(parameters('dataExports'))]" + "count": "[length(coalesce(parameters('dataExports'), createArray()))]" }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -1168,31 +1877,65 @@ "value": "[parameters('name')]" }, "name": { - "value": "[parameters('dataExports')[copyIndex()].name]" + "value": "[coalesce(parameters('dataExports'), createArray())[copyIndex()].name]" }, "destination": { - "value": "[tryGet(parameters('dataExports')[copyIndex()], 'destination')]" + "value": "[tryGet(coalesce(parameters('dataExports'), createArray())[copyIndex()], 'destination')]" }, "enable": { - "value": "[tryGet(parameters('dataExports')[copyIndex()], 'enable')]" + "value": "[tryGet(coalesce(parameters('dataExports'), createArray())[copyIndex()], 'enable')]" }, "tableNames": { - "value": "[tryGet(parameters('dataExports')[copyIndex()], 'tableNames')]" + "value": "[tryGet(coalesce(parameters('dataExports'), createArray())[copyIndex()], 'tableNames')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5765609820817623497" + "version": "0.31.92.45157", + "templateHash": "8392467222383128491" }, "name": "Log Analytics Workspace Data Exports", "description": "This module deploys a Log Analytics Workspace Data Export.", "owner": "Azure/module-maintainers" }, + "definitions": { + "destinationType": { + "type": "object", + "properties": { + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The destination resource ID." + } + }, + "metaData": { + "type": "object", + "properties": { + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Allows to define an Event Hub name. Not applicable when destination is Storage Account." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The destination metadata." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The data export destination properties." + } + } + }, "parameters": { "name": { "type": "string", @@ -1209,8 +1952,8 @@ } }, "destination": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/destinationType", + "nullable": true, "metadata": { "description": "Optional. Destination properties." } @@ -1224,14 +1967,23 @@ }, "tableNames": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "minLength": 1, "metadata": { - "description": "Optional. An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']." + "description": "Required. An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']." } } }, - "resources": [ - { + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('workspaceName')]" + }, + "dataExport": { "type": "Microsoft.OperationalInsights/workspaces/dataExports", "apiVersion": "2020-08-01", "name": "[format('{0}/{1}', parameters('workspaceName'), parameters('name'))]", @@ -1239,9 +1991,12 @@ "destination": "[parameters('destination')]", "enable": "[parameters('enable')]", "tableNames": "[parameters('tableNames')]" - } + }, + "dependsOn": [ + "workspace" + ] } - ], + }, "outputs": { "name": { "type": "string", @@ -1274,7 +2029,7 @@ "logAnalyticsWorkspace_dataSources": { "copy": { "name": "logAnalyticsWorkspace_dataSources", - "count": "[length(parameters('dataSources'))]" + "count": "[length(coalesce(parameters('dataSources'), createArray()))]" }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -1289,43 +2044,46 @@ "value": "[parameters('name')]" }, "name": { - "value": "[parameters('dataSources')[copyIndex()].name]" + "value": "[coalesce(parameters('dataSources'), createArray())[copyIndex()].name]" }, "kind": { - "value": "[parameters('dataSources')[copyIndex()].kind]" + "value": "[coalesce(parameters('dataSources'), createArray())[copyIndex()].kind]" }, "linkedResourceId": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'linkedResourceId')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'linkedResourceId')]" }, "eventLogName": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'eventLogName')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'eventLogName')]" }, "eventTypes": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'eventTypes')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'eventTypes')]" }, "objectName": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'objectName')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'objectName')]" }, "instanceName": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'instanceName')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'instanceName')]" }, "intervalSeconds": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'intervalSeconds')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'intervalSeconds')]" }, "counterName": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'counterName')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'counterName')]" }, "state": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'state')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'state')]" }, "syslogName": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'syslogName')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'syslogName')]" }, "syslogSeverities": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'syslogSeverities')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'syslogSeverities')]" }, "performanceCounters": { - "value": "[tryGet(parameters('dataSources')[copyIndex()], 'performanceCounters')]" + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'performanceCounters')]" + }, + "tags": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'tags')]" } }, "template": { @@ -1335,8 +2093,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13460038983765020046" + "version": "0.31.92.45157", + "templateHash": "3019400626196043317" }, "name": "Log Analytics Workspace Datasources", "description": "This module deploys a Log Analytics Workspace Data Source.", @@ -1352,7 +2110,7 @@ "name": { "type": "string", "metadata": { - "description": "Required. Name of the solution." + "description": "Required. Name of the data source." } }, "kind": { @@ -1369,7 +2127,7 @@ "LinuxPerformanceCollection" ], "metadata": { - "description": "Required. The kind of the DataSource." + "description": "Optional. The kind of the data source." } }, "tags": { @@ -1381,14 +2139,14 @@ }, "linkedResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Resource ID of the resource to be linked." } }, "eventLogName": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Windows event log name to configure when kind is WindowsEvent." } @@ -1402,7 +2160,7 @@ }, "objectName": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." } @@ -1430,21 +2188,21 @@ }, "counterName": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Counter name to configure when kind is WindowsPerformanceCounter." } }, "state": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection." } }, "syslogName": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. System log to configure when kind is LinuxSyslog." } @@ -1520,7 +2278,7 @@ "logAnalyticsWorkspace_tables": { "copy": { "name": "logAnalyticsWorkspace_tables", - "count": "[length(parameters('tables'))]" + "count": "[length(coalesce(parameters('tables'), createArray()))]" }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -1535,28 +2293,28 @@ "value": "[parameters('name')]" }, "name": { - "value": "[parameters('tables')[copyIndex()].name]" + "value": "[coalesce(parameters('tables'), createArray())[copyIndex()].name]" }, "plan": { - "value": "[tryGet(parameters('tables')[copyIndex()], 'plan')]" + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'plan')]" }, "schema": { - "value": "[tryGet(parameters('tables')[copyIndex()], 'schema')]" + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'schema')]" }, "retentionInDays": { - "value": "[tryGet(parameters('tables')[copyIndex()], 'retentionInDays')]" + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'retentionInDays')]" }, "totalRetentionInDays": { - "value": "[tryGet(parameters('tables')[copyIndex()], 'totalRetentionInDays')]" + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'totalRetentionInDays')]" }, "restoredLogs": { - "value": "[tryGet(parameters('tables')[copyIndex()], 'restoredLogs')]" + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'restoredLogs')]" }, "searchResults": { - "value": "[tryGet(parameters('tables')[copyIndex()], 'searchResults')]" + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'searchResults')]" }, "roleAssignments": { - "value": "[tryGet(parameters('tables')[copyIndex()], 'roleAssignments')]" + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'roleAssignments')]" } }, "template": { @@ -1566,86 +2324,257 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10380077652898392916" + "version": "0.31.92.45157", + "templateHash": "13277383761731431931" }, "name": "Log Analytics Workspace Tables", "description": "This module deploys a Log Analytics Workspace Table.", "owner": "Azure/module-maintainers" }, "definitions": { - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } + "restoredLogsType": { + "type": "object", + "properties": { + "sourceTable": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table to restore data from." + } + }, + "startRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the restore from (UTC)." + } + }, + "endRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the restore by (UTC)." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The parameters of the restore operation that initiated the table." + } + }, + "schemaType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The table name." + } + }, + "columns": { + "type": "array", + "items": { + "$ref": "#/definitions/columnType" }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "metadata": { + "description": "Required. A list of table custom columns." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table description." + } + }, + "displayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table display name." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The table schema." + } + }, + "columnType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The column name." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "boolean", + "dateTime", + "dynamic", + "guid", + "int", + "long", + "real", + "string" + ], + "metadata": { + "description": "Required. The column type." + } + }, + "dataTypeHint": { + "type": "string", + "allowedValues": [ + "armPath", + "guid", + "ip", + "uri" + ], + "nullable": true, + "metadata": { + "description": "Optional. The column data type logical hint." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The column description." + } + }, + "displayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Column display name." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The parameters of the table column." + } + }, + "searchResultsType": { + "type": "object", + "properties": { + "query": { + "type": "string", + "metadata": { + "description": "Required. The search job query." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The search description." + } + }, + "limit": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Limit the search job to return up to specified number of rows." + } + }, + "startSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the search from (UTC)." + } + }, + "endSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the search by (UTC)." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The parameters of the search job that initiated the table." + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -1673,8 +2602,8 @@ } }, "restoredLogs": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/restoredLogsType", + "nullable": true, "metadata": { "description": "Optional. Restore parameters." } @@ -1689,15 +2618,15 @@ } }, "schema": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/schemaType", + "nullable": true, "metadata": { "description": "Optional. Table's schema." } }, "searchResults": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/searchResultsType", + "nullable": true, "metadata": { "description": "Optional. Parameters of the search job that initiated this table." } @@ -1712,7 +2641,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -1816,7 +2749,7 @@ "logAnalyticsWorkspace_solutions": { "copy": { "name": "logAnalyticsWorkspace_solutions", - "count": "[length(parameters('gallerySolutions'))]" + "count": "[length(coalesce(parameters('gallerySolutions'), createArray()))]" }, "condition": "[not(empty(parameters('gallerySolutions')))]", "type": "Microsoft.Resources/deployments", @@ -1829,7 +2762,7 @@ "mode": "Incremental", "parameters": { "name": { - "value": "[parameters('gallerySolutions')[copyIndex()].name]" + "value": "[coalesce(parameters('gallerySolutions'), createArray())[copyIndex()].name]" }, "location": { "value": "[parameters('location')]" @@ -1837,34 +2770,68 @@ "logAnalyticsWorkspaceName": { "value": "[parameters('name')]" }, - "product": { - "value": "[tryGet(parameters('gallerySolutions')[copyIndex()], 'product')]" - }, - "publisher": { - "value": "[tryGet(parameters('gallerySolutions')[copyIndex()], 'publisher')]" + "plan": { + "value": "[coalesce(parameters('gallerySolutions'), createArray())[copyIndex()].plan]" }, "enableTelemetry": { - "value": "[coalesce(tryGet(parameters('gallerySolutions')[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + "value": "[coalesce(tryGet(coalesce(parameters('gallerySolutions'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18444780972506374592" + "version": "0.30.23.60470", + "templateHash": "1867653058254938383" }, "name": "Operations Management Solutions", "description": "This module deploys an Operations Management Solution.", "owner": "Azure/module-maintainers" }, + "definitions": { + "solutionPlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the solution to be created.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, it can be anything.\nThe solution type is case-sensitive.\nIf not provided, the value of the `name` parameter will be used." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product name of the deployed solution.\nFor Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.\nFor a third party solution, it can be anything.\nThis is case sensitive." + } + }, + "publisher": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", "metadata": { - "description": "Required. Name of the solution. For Microsoft published gallery solution the target solution resource name will be composed as `{name}({logAnalyticsWorkspaceName})`." + "description": "Required. Name of the solution.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.\nThe solution type is case-sensitive." + } + }, + "plan": { + "$ref": "#/definitions/solutionPlanType", + "metadata": { + "description": "Required. Plan for solution object supported by the OperationsManagement resource provider." } }, "logAnalyticsWorkspaceName": { @@ -1880,20 +2847,6 @@ "description": "Optional. Location for all resources." } }, - "product": { - "type": "string", - "defaultValue": "OMSGallery", - "metadata": { - "description": "Optional. The product of the deployed solution. For Microsoft published gallery solution it should be `OMSGallery` and the target solution resource product will be composed as `OMSGallery/{name}`. For third party solution, it can be anything. This is case sensitive." - } - }, - "publisher": { - "type": "string", - "defaultValue": "Microsoft", - "metadata": { - "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`." - } - }, "enableTelemetry": { "type": "bool", "defaultValue": true, @@ -1902,16 +2855,12 @@ } } }, - "variables": { - "solutionName": "[if(equals(parameters('publisher'), 'Microsoft'), format('{0}({1})', parameters('name'), parameters('logAnalyticsWorkspaceName')), parameters('name'))]", - "solutionProduct": "[if(equals(parameters('publisher'), 'Microsoft'), format('OMSGallery/{0}', parameters('name')), parameters('product'))]" - }, - "resources": [ - { + "resources": { + "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.operationsmanagement-solution.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.operationsmanagement-solution.{0}.{1}', replace('0.3.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1927,36 +2876,45 @@ } } }, - { + "logAnalyticsWorkspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2021-06-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "solution": { "type": "Microsoft.OperationsManagement/solutions", "apiVersion": "2015-11-01-preview", - "name": "[variables('solutionName')]", + "name": "[parameters('name')]", "location": "[parameters('location')]", "properties": { "workspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]" }, "plan": { - "name": "[variables('solutionName')]", + "name": "[coalesce(tryGet(parameters('plan'), 'name'), parameters('name'))]", "promotionCode": "", - "product": "[variables('solutionProduct')]", - "publisher": "[parameters('publisher')]" - } + "product": "[parameters('plan').product]", + "publisher": "[coalesce(tryGet(parameters('plan'), 'publisher'), 'Microsoft')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] } - ], + }, "outputs": { "name": { "type": "string", "metadata": { "description": "The name of the deployed solution." }, - "value": "[variables('solutionName')]" + "value": "[parameters('name')]" }, "resourceId": { "type": "string", "metadata": { "description": "The resource ID of the deployed solution." }, - "value": "[resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName'))]" + "value": "[resourceId('Microsoft.OperationsManagement/solutions', parameters('name'))]" }, "resourceGroupName": { "type": "string", @@ -1970,7 +2928,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName')), '2015-11-01-preview', 'full').location]" + "value": "[reference('solution', '2015-11-01-preview', 'full').location]" } } } diff --git a/avm/res/operational-insights/workspace/saved-search/main.json b/avm/res/operational-insights/workspace/saved-search/main.json index 88711e3f27..645e600903 100644 --- a/avm/res/operational-insights/workspace/saved-search/main.json +++ b/avm/res/operational-insights/workspace/saved-search/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7683333179440464721" + "version": "0.31.92.45157", + "templateHash": "15600200446151630277" }, "name": "Log Analytics Workspace Saved Searches", "description": "This module deploys a Log Analytics Workspace Saved Search.", diff --git a/avm/res/operational-insights/workspace/storage-insight-config/README.md b/avm/res/operational-insights/workspace/storage-insight-config/README.md index 67797b8b01..8bd800b2d2 100644 --- a/avm/res/operational-insights/workspace/storage-insight-config/README.md +++ b/avm/res/operational-insights/workspace/storage-insight-config/README.md @@ -57,7 +57,6 @@ The names of the blob containers that the workspace should read. - Required: No - Type: array -- Default: `[]` ### Parameter: `name` @@ -73,7 +72,6 @@ The names of the Azure tables that the workspace should read. - Required: No - Type: array -- Default: `[]` ### Parameter: `tags` diff --git a/avm/res/operational-insights/workspace/storage-insight-config/main.bicep b/avm/res/operational-insights/workspace/storage-insight-config/main.bicep index 81da4012c7..6d90355bda 100644 --- a/avm/res/operational-insights/workspace/storage-insight-config/main.bicep +++ b/avm/res/operational-insights/workspace/storage-insight-config/main.bicep @@ -12,10 +12,10 @@ param name string = '${last(split(storageAccountResourceId, '/'))}-stinsconfig' param storageAccountResourceId string @description('Optional. The names of the blob containers that the workspace should read.') -param containers array = [] +param containers string[]? @description('Optional. The names of the Azure tables that the workspace should read.') -param tables array = [] +param tables string[]? @description('Optional. Tags to configure in the resource.') param tags object? diff --git a/avm/res/operational-insights/workspace/storage-insight-config/main.json b/avm/res/operational-insights/workspace/storage-insight-config/main.json index 2c3b360f01..a344a30e2a 100644 --- a/avm/res/operational-insights/workspace/storage-insight-config/main.json +++ b/avm/res/operational-insights/workspace/storage-insight-config/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "1745671120474305926" + "version": "0.31.92.45157", + "templateHash": "156138954055342275" }, "name": "Log Analytics Workspace Storage Insight Configs", "description": "This module deploys a Log Analytics Workspace Storage Insight Config.", @@ -34,14 +34,20 @@ }, "containers": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "nullable": true, "metadata": { "description": "Optional. The names of the blob containers that the workspace should read." } }, "tables": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "nullable": true, "metadata": { "description": "Optional. The names of the Azure tables that the workspace should read." } diff --git a/avm/res/operational-insights/workspace/table/README.md b/avm/res/operational-insights/workspace/table/README.md index dc20f643c0..a9c0f4d783 100644 --- a/avm/res/operational-insights/workspace/table/README.md +++ b/avm/res/operational-insights/workspace/table/README.md @@ -7,6 +7,7 @@ This module deploys a Log Analytics Workspace Table. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -76,7 +77,35 @@ Restore parameters. - Required: No - Type: object -- Default: `{}` + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`endRestoreTime`](#parameter-restoredlogsendrestoretime) | string | The timestamp to end the restore by (UTC). | +| [`sourceTable`](#parameter-restoredlogssourcetable) | string | The table to restore data from. | +| [`startRestoreTime`](#parameter-restoredlogsstartrestoretime) | string | The timestamp to start the restore from (UTC). | + +### Parameter: `restoredLogs.endRestoreTime` + +The timestamp to end the restore by (UTC). + +- Required: No +- Type: string + +### Parameter: `restoredLogs.sourceTable` + +The table to restore data from. + +- Required: No +- Type: string + +### Parameter: `restoredLogs.startRestoreTime` + +The timestamp to start the restore from (UTC). + +- Required: No +- Type: string ### Parameter: `retentionInDays` @@ -199,7 +228,120 @@ Table's schema. - Required: No - Type: object -- Default: `{}` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`columns`](#parameter-schemacolumns) | array | A list of table custom columns. | +| [`name`](#parameter-schemaname) | string | The table name. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-schemadescription) | string | The table description. | +| [`displayName`](#parameter-schemadisplayname) | string | The table display name. | + +### Parameter: `schema.columns` + +A list of table custom columns. + +- Required: Yes +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-schemacolumnsname) | string | The column name. | +| [`type`](#parameter-schemacolumnstype) | string | The column type. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`dataTypeHint`](#parameter-schemacolumnsdatatypehint) | string | The column data type logical hint. | +| [`description`](#parameter-schemacolumnsdescription) | string | The column description. | +| [`displayName`](#parameter-schemacolumnsdisplayname) | string | Column display name. | + +### Parameter: `schema.columns.name` + +The column name. + +- Required: Yes +- Type: string + +### Parameter: `schema.columns.type` + +The column type. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'boolean' + 'dateTime' + 'dynamic' + 'guid' + 'int' + 'long' + 'real' + 'string' + ] + ``` + +### Parameter: `schema.columns.dataTypeHint` + +The column data type logical hint. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'armPath' + 'guid' + 'ip' + 'uri' + ] + ``` + +### Parameter: `schema.columns.description` + +The column description. + +- Required: No +- Type: string + +### Parameter: `schema.columns.displayName` + +Column display name. + +- Required: No +- Type: string + +### Parameter: `schema.name` + +The table name. + +- Required: Yes +- Type: string + +### Parameter: `schema.description` + +The table description. + +- Required: No +- Type: string + +### Parameter: `schema.displayName` + +The table display name. + +- Required: No +- Type: string ### Parameter: `searchResults` @@ -207,7 +349,56 @@ Parameters of the search job that initiated this table. - Required: No - Type: object -- Default: `{}` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`query`](#parameter-searchresultsquery) | string | The search job query. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-searchresultsdescription) | string | The search description. | +| [`endSearchTime`](#parameter-searchresultsendsearchtime) | string | The timestamp to end the search by (UTC). | +| [`limit`](#parameter-searchresultslimit) | int | Limit the search job to return up to specified number of rows. | +| [`startSearchTime`](#parameter-searchresultsstartsearchtime) | string | The timestamp to start the search from (UTC). | + +### Parameter: `searchResults.query` + +The search job query. + +- Required: Yes +- Type: string + +### Parameter: `searchResults.description` + +The search description. + +- Required: No +- Type: string + +### Parameter: `searchResults.endSearchTime` + +The timestamp to end the search by (UTC). + +- Required: No +- Type: string + +### Parameter: `searchResults.limit` + +Limit the search job to return up to specified number of rows. + +- Required: No +- Type: int + +### Parameter: `searchResults.startSearchTime` + +The timestamp to start the search from (UTC). + +- Required: No +- Type: string ### Parameter: `totalRetentionInDays` @@ -224,3 +415,11 @@ The table total retention in days, between 4 and 2555. Setting this property to | `name` | string | The name of the table. | | `resourceGroupName` | string | The name of the resource group the table was created in. | | `resourceId` | string | The resource ID of the table. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/operational-insights/workspace/table/main.bicep b/avm/res/operational-insights/workspace/table/main.bicep index b38ff9210f..98aea3459e 100644 --- a/avm/res/operational-insights/workspace/table/main.bicep +++ b/avm/res/operational-insights/workspace/table/main.bicep @@ -20,7 +20,7 @@ param workspaceName string param plan string = 'Analytics' @description('Optional. Restore parameters.') -param restoredLogs object = {} +param restoredLogs restoredLogsType? @description('Optional. The table retention in days, between 4 and 730. Setting this property to -1 will default to the workspace retention.') @minValue(-1) @@ -28,18 +28,19 @@ param restoredLogs object = {} param retentionInDays int = -1 @description('Optional. Table\'s schema.') -param schema object = {} +param schema schemaType? @description('Optional. Parameters of the search job that initiated this table.') -param searchResults object = {} +param searchResults searchResultsType? @description('Optional. The table total retention in days, between 4 and 2555. Setting this property to -1 will default to table retention.') @minValue(-1) @maxValue(2555) param totalRetentionInDays int = -1 +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -136,28 +137,56 @@ output resourceGroupName string = resourceGroup().name // Definitions // // =============== // -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? +@export() +@description('The parameters of the restore operation that initiated the table.') +type restoredLogsType = { + @description('Optional. The table to restore data from.') + sourceTable: string? + @description('Optional. The timestamp to start the restore from (UTC).') + startRestoreTime: string? + @description('Optional. The timestamp to end the restore by (UTC).') + endRestoreTime: string? +} - @description('Optional. The description of the role assignment.') +@export() +@description('The table schema.') +type schemaType = { + @description('Required. The table name.') + name: string + @description('Required. A list of table custom columns.') + columns: columnType[] + @description('Optional. The table description.') description: string? + @description('Optional. The table display name.') + displayName: string? +} - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? +@export() +@description('The parameters of the table column.') +type columnType = { + @description('Required. The column name.') + name: string + @description('Required. The column type.') + type: 'boolean' | 'dateTime' | 'dynamic' | 'guid' | 'int' | 'long' | 'real' | 'string' + @description('Optional. The column data type logical hint.') + dataTypeHint: 'armPath' | 'guid' | 'ip' | 'uri'? + @description('Optional. The column description.') + description: string? + @description('Optional. Column display name.') + displayName: string? +} - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? +@export() +@description('The parameters of the search job that initiated the table.') +type searchResultsType = { + @description('Required. The search job query.') + query: string + @description('Optional. The search description.') + description: string? + @description('Optional. Limit the search job to return up to specified number of rows.') + limit: int? + @description('Optional. The timestamp to start the search from (UTC).') + startSearchTime: string? + @description('Optional. The timestamp to end the search by (UTC).') + endSearchTime: string? +} diff --git a/avm/res/operational-insights/workspace/table/main.json b/avm/res/operational-insights/workspace/table/main.json index 6a1e1e11a6..5c56c36063 100644 --- a/avm/res/operational-insights/workspace/table/main.json +++ b/avm/res/operational-insights/workspace/table/main.json @@ -5,86 +5,257 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10380077652898392916" + "version": "0.31.92.45157", + "templateHash": "13277383761731431931" }, "name": "Log Analytics Workspace Tables", "description": "This module deploys a Log Analytics Workspace Table.", "owner": "Azure/module-maintainers" }, "definitions": { - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } + "restoredLogsType": { + "type": "object", + "properties": { + "sourceTable": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table to restore data from." + } + }, + "startRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the restore from (UTC)." + } + }, + "endRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the restore by (UTC)." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The parameters of the restore operation that initiated the table." + } + }, + "schemaType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The table name." + } + }, + "columns": { + "type": "array", + "items": { + "$ref": "#/definitions/columnType" }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "metadata": { + "description": "Required. A list of table custom columns." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table description." + } + }, + "displayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table display name." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The table schema." + } + }, + "columnType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The column name." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "boolean", + "dateTime", + "dynamic", + "guid", + "int", + "long", + "real", + "string" + ], + "metadata": { + "description": "Required. The column type." + } + }, + "dataTypeHint": { + "type": "string", + "allowedValues": [ + "armPath", + "guid", + "ip", + "uri" + ], + "nullable": true, + "metadata": { + "description": "Optional. The column data type logical hint." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The column description." + } + }, + "displayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Column display name." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true, + "description": "The parameters of the table column." + } + }, + "searchResultsType": { + "type": "object", + "properties": { + "query": { + "type": "string", + "metadata": { + "description": "Required. The search job query." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The search description." + } + }, + "limit": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Limit the search job to return up to specified number of rows." + } + }, + "startSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the search from (UTC)." + } + }, + "endSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the search by (UTC)." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The parameters of the search job that initiated the table." + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -112,8 +283,8 @@ } }, "restoredLogs": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/restoredLogsType", + "nullable": true, "metadata": { "description": "Optional. Restore parameters." } @@ -128,15 +299,15 @@ } }, "schema": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/schemaType", + "nullable": true, "metadata": { "description": "Optional. Table's schema." } }, "searchResults": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/searchResultsType", + "nullable": true, "metadata": { "description": "Optional. Parameters of the search job that initiated this table." } @@ -151,7 +322,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/operational-insights/workspace/tests/e2e/adv/main.test.bicep b/avm/res/operational-insights/workspace/tests/e2e/adv/main.test.bicep index 94d627e6a7..56fbf274a5 100644 --- a/avm/res/operational-insights/workspace/tests/e2e/adv/main.test.bicep +++ b/avm/res/operational-insights/workspace/tests/e2e/adv/main.test.bicep @@ -186,9 +186,10 @@ module testDeployment '../../../main.bicep' = [ ] gallerySolutions: [ { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'AzureAutomation(${namePrefix}${serviceShort}001)' + plan: { + product: 'OMSGallery/AzureAutomation' + } } ] linkedServices: [ @@ -200,7 +201,9 @@ module testDeployment '../../../main.bicep' = [ linkedStorageAccounts: [ { name: 'Query' - resourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountIds: [ + nestedDependencies.outputs.storageAccountResourceId + ] } ] publicNetworkAccessForIngestion: 'Disabled' @@ -233,11 +236,11 @@ module testDeployment '../../../main.bicep' = [ columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'RawData' - type: 'String' + type: 'string' } ] } @@ -271,27 +274,27 @@ module testDeployment '../../../main.bicep' = [ columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'EventTime' - type: 'DateTime' + type: 'dateTime' } { name: 'EventLevel' - type: 'String' + type: 'string' } { name: 'EventCode' - type: 'Int' + type: 'int' } { name: 'Message' - type: 'String' + type: 'string' } { name: 'RawData' - type: 'String' + type: 'string' } ] } diff --git a/avm/res/operational-insights/workspace/tests/e2e/max/main.test.bicep b/avm/res/operational-insights/workspace/tests/e2e/max/main.test.bicep index 4b277bc3f5..c2d85a7fde 100644 --- a/avm/res/operational-insights/workspace/tests/e2e/max/main.test.bicep +++ b/avm/res/operational-insights/workspace/tests/e2e/max/main.test.bicep @@ -175,11 +175,28 @@ module testDeployment '../../../main.bicep' = [ ] gallerySolutions: [ { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'AzureAutomation(${namePrefix}${serviceShort}001)' + plan: { + product: 'OMSGallery/AzureAutomation' + } + } + { + name: 'SecurityInsights(${namePrefix}${serviceShort}001)' + plan: { + product: 'OMSGallery/SecurityInsights' + publisher: 'Microsoft' + } + } + { + name: 'SQLAuditing(${namePrefix}${serviceShort}001)' + plan: { + name: 'SQLAuditing(${namePrefix}${serviceShort}001)' + product: 'SQLAuditing' + publisher: 'Microsoft' + } } ] + onboardWorkspaceToSentinel: true linkedServices: [ { name: 'Automation' @@ -189,7 +206,9 @@ module testDeployment '../../../main.bicep' = [ linkedStorageAccounts: [ { name: 'Query' - resourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountIds: [ + nestedDependencies.outputs.storageAccountResourceId + ] } ] tables: [ @@ -200,11 +219,11 @@ module testDeployment '../../../main.bicep' = [ columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'RawData' - type: 'String' + type: 'string' } ] } @@ -238,27 +257,27 @@ module testDeployment '../../../main.bicep' = [ columns: [ { name: 'TimeGenerated' - type: 'DateTime' + type: 'dateTime' } { name: 'EventTime' - type: 'DateTime' + type: 'dateTime' } { name: 'EventLevel' - type: 'String' + type: 'string' } { name: 'EventCode' - type: 'Int' + type: 'int' } { name: 'Message' - type: 'String' + type: 'string' } { name: 'RawData' - type: 'String' + type: 'string' } ] } diff --git a/avm/res/operational-insights/workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/operational-insights/workspace/tests/e2e/waf-aligned/main.test.bicep index 62e91d5492..80c5cfb578 100644 --- a/avm/res/operational-insights/workspace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/operational-insights/workspace/tests/e2e/waf-aligned/main.test.bicep @@ -168,9 +168,10 @@ module testDeployment '../../../main.bicep' = [ ] gallerySolutions: [ { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' + name: 'AzureAutomation(${namePrefix}${serviceShort}001)' + plan: { + product: 'OMSGallery/AzureAutomation' + } } ] linkedServices: [ @@ -182,7 +183,9 @@ module testDeployment '../../../main.bicep' = [ linkedStorageAccounts: [ { name: 'Query' - resourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountIds: [ + nestedDependencies.outputs.storageAccountResourceId + ] } ] publicNetworkAccessForIngestion: 'Disabled' diff --git a/avm/res/operational-insights/workspace/version.json b/avm/res/operational-insights/workspace/version.json index 7e1d3f4157..b39a201436 100644 --- a/avm/res/operational-insights/workspace/version.json +++ b/avm/res/operational-insights/workspace/version.json @@ -1,7 +1,7 @@ { - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.7", - "pathFilters": [ - "./main.json" - ] -} \ No newline at end of file + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.9", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/operations-management/solution/README.md b/avm/res/operations-management/solution/README.md index f8f05da8f6..6d4b835b48 100644 --- a/avm/res/operations-management/solution/README.md +++ b/avm/res/operations-management/solution/README.md @@ -27,7 +27,8 @@ The following section provides usage examples for the module, which were used to - [Using only defaults](#example-1-using-only-defaults) - [Microsoft solution](#example-2-microsoft-solution) - [Non-Microsoft solution](#example-3-non-microsoft-solution) -- [WAF-aligned](#example-4-waf-aligned) +- [SQLAuditing solution](#example-4-sqlauditing-solution) +- [WAF-aligned](#example-5-waf-aligned) ### Example 1: _Using only defaults_ @@ -44,7 +45,10 @@ module solution 'br/public:avm/res/operations-management/solution:' = { params: { // Required parameters logAnalyticsWorkspaceName: '' - name: 'Updates' + name: '' + plan: { + product: 'OMSGallery/Updates' + } // Non-required parameters location: '' } @@ -68,7 +72,12 @@ module solution 'br/public:avm/res/operations-management/solution:' = { "value": "" }, "name": { - "value": "Updates" + "value": "" + }, + "plan": { + "value": { + "product": "OMSGallery/Updates" + } }, // Non-required parameters "location": { @@ -90,7 +99,10 @@ using 'br/public:avm/res/operations-management/solution:' // Required parameters param logAnalyticsWorkspaceName = '' -param name = 'Updates' +param name = '' +param plan = { + product: 'OMSGallery/Updates' +} // Non-required parameters param location = '' ``` @@ -113,11 +125,12 @@ module solution 'br/public:avm/res/operations-management/solution:' = { params: { // Required parameters logAnalyticsWorkspaceName: '' - name: 'AzureAutomation' + name: '' + plan: { + product: 'OMSGallery/AzureAutomation' + } // Non-required parameters location: '' - product: 'OMSGallery' - publisher: 'Microsoft' } } ``` @@ -139,17 +152,16 @@ module solution 'br/public:avm/res/operations-management/solution:' = { "value": "" }, "name": { - "value": "AzureAutomation" + "value": "" + }, + "plan": { + "value": { + "product": "OMSGallery/AzureAutomation" + } }, // Non-required parameters "location": { "value": "" - }, - "product": { - "value": "OMSGallery" - }, - "publisher": { - "value": "Microsoft" } } } @@ -167,11 +179,12 @@ using 'br/public:avm/res/operations-management/solution:' // Required parameters param logAnalyticsWorkspaceName = '' -param name = 'AzureAutomation' +param name = '' +param plan = { + product: 'OMSGallery/AzureAutomation' +} // Non-required parameters param location = '' -param product = 'OMSGallery' -param publisher = 'Microsoft' ``` @@ -193,10 +206,13 @@ module solution 'br/public:avm/res/operations-management/solution:' = { // Required parameters logAnalyticsWorkspaceName: '' name: 'omsnonms001' + plan: { + name: 'nonmsTestSolutionPlan' + product: 'nonmsTestSolutionProduct' + publisher: 'nonmsTestSolutionPublisher' + } // Non-required parameters location: '' - product: 'nonmsTestSolutionProduct' - publisher: 'nonmsTestSolutionPublisher' } } ``` @@ -220,15 +236,16 @@ module solution 'br/public:avm/res/operations-management/solution:' = { "name": { "value": "omsnonms001" }, + "plan": { + "value": { + "name": "nonmsTestSolutionPlan", + "product": "nonmsTestSolutionProduct", + "publisher": "nonmsTestSolutionPublisher" + } + }, // Non-required parameters "location": { "value": "" - }, - "product": { - "value": "nonmsTestSolutionProduct" - }, - "publisher": { - "value": "nonmsTestSolutionPublisher" } } } @@ -247,18 +264,21 @@ using 'br/public:avm/res/operations-management/solution:' // Required parameters param logAnalyticsWorkspaceName = '' param name = 'omsnonms001' +param plan = { + name: 'nonmsTestSolutionPlan' + product: 'nonmsTestSolutionProduct' + publisher: 'nonmsTestSolutionPublisher' +} // Non-required parameters param location = '' -param product = 'nonmsTestSolutionProduct' -param publisher = 'nonmsTestSolutionPublisher' ```

    -### Example 4: _WAF-aligned_ +### Example 4: _SQLAuditing solution_ -This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. +This instance deploys the module with the SQLAuditing solution. This solution is authored by Microsoft, but uses a non-standard value for the `product` parameter.

    @@ -271,11 +291,13 @@ module solution 'br/public:avm/res/operations-management/solution:' = { params: { // Required parameters logAnalyticsWorkspaceName: '' - name: 'AzureAutomation' + name: '' + plan: { + product: 'SQLAuditing' + publisher: 'Microsoft' + } // Non-required parameters location: '' - product: 'OMSGallery' - publisher: 'Microsoft' } } ``` @@ -297,17 +319,102 @@ module solution 'br/public:avm/res/operations-management/solution:' = { "value": "" }, "name": { - "value": "AzureAutomation" + "value": "" + }, + "plan": { + "value": { + "product": "SQLAuditing", + "publisher": "Microsoft" + } }, // Non-required parameters "location": { "value": "" + } + } +} +``` + +
    +

    + +

    + +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/operations-management/solution:' + +// Required parameters +param logAnalyticsWorkspaceName = '' +param name = '' +param plan = { + product: 'SQLAuditing' + publisher: 'Microsoft' +} +// Non-required parameters +param location = '' +``` + +
    +

    + +### Example 5: _WAF-aligned_ + +This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. + + +

    + +via Bicep module + +```bicep +module solution 'br/public:avm/res/operations-management/solution:' = { + name: 'solutionDeployment' + params: { + // Required parameters + logAnalyticsWorkspaceName: '' + name: '' + plan: { + name: '' + product: 'OMSGallery/AzureAutomation' + publisher: 'Microsoft' + } + // Non-required parameters + location: '' + } +} +``` + +
    +

    + +

    + +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "logAnalyticsWorkspaceName": { + "value": "" + }, + "name": { + "value": "" }, - "product": { - "value": "OMSGallery" + "plan": { + "value": { + "name": "", + "product": "OMSGallery/AzureAutomation", + "publisher": "Microsoft" + } }, - "publisher": { - "value": "Microsoft" + // Non-required parameters + "location": { + "value": "" } } } @@ -325,11 +432,14 @@ using 'br/public:avm/res/operations-management/solution:' // Required parameters param logAnalyticsWorkspaceName = '' -param name = 'AzureAutomation' +param name = '' +param plan = { + name: '' + product: 'OMSGallery/AzureAutomation' + publisher: 'Microsoft' +} // Non-required parameters param location = '' -param product = 'OMSGallery' -param publisher = 'Microsoft' ```
    @@ -342,7 +452,8 @@ param publisher = 'Microsoft' | Parameter | Type | Description | | :-- | :-- | :-- | | [`logAnalyticsWorkspaceName`](#parameter-loganalyticsworkspacename) | string | Name of the Log Analytics workspace where the solution will be deployed/enabled. | -| [`name`](#parameter-name) | string | Name of the solution. For Microsoft published gallery solution the target solution resource name will be composed as `{name}({logAnalyticsWorkspaceName})`. | +| [`name`](#parameter-name) | string | Name of the solution.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.

    The solution type is case-sensitive. | +| [`plan`](#parameter-plan) | object | Plan for solution object supported by the OperationsManagement resource provider. | **Optional parameters** @@ -350,8 +461,6 @@ param publisher = 'Microsoft' | :-- | :-- | :-- | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`location`](#parameter-location) | string | Location for all resources. | -| [`product`](#parameter-product) | string | The product of the deployed solution. For Microsoft published gallery solution it should be `OMSGallery` and the target solution resource product will be composed as `OMSGallery/{name}`. For third party solution, it can be anything. This is case sensitive. | -| [`publisher`](#parameter-publisher) | string | The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`. | ### Parameter: `logAnalyticsWorkspaceName` @@ -362,42 +471,67 @@ Name of the Log Analytics workspace where the solution will be deployed/enabled. ### Parameter: `name` -Name of the solution. For Microsoft published gallery solution the target solution resource name will be composed as `{name}({logAnalyticsWorkspaceName})`. +Name of the solution.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.

    The solution type is case-sensitive. - Required: Yes - Type: string -### Parameter: `enableTelemetry` +### Parameter: `plan` -Enable/Disable usage telemetry for module. +Plan for solution object supported by the OperationsManagement resource provider. -- Required: No -- Type: bool -- Default: `True` +- Required: Yes +- Type: object -### Parameter: `location` +**Required parameters** -Location for all resources. +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`product`](#parameter-planproduct) | string | The product name of the deployed solution.

    For Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.

    For a third party solution, it can be anything.

    This is case sensitive. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-planname) | string | Name of the solution to be created.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, it can be anything.

    The solution type is case-sensitive.

    If not provided, the value of the `name` parameter will be used. | +| [`publisher`](#parameter-planpublisher) | string | The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value. | + +### Parameter: `plan.product` + +The product name of the deployed solution.

    For Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.

    For a third party solution, it can be anything.

    This is case sensitive. + +- Required: Yes +- Type: string + +### Parameter: `plan.name` + +Name of the solution to be created.

    For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.

    For solutions authored by third parties, it can be anything.

    The solution type is case-sensitive.

    If not provided, the value of the `name` parameter will be used. - Required: No - Type: string -- Default: `[resourceGroup().location]` -### Parameter: `product` +### Parameter: `plan.publisher` -The product of the deployed solution. For Microsoft published gallery solution it should be `OMSGallery` and the target solution resource product will be composed as `OMSGallery/{name}`. For third party solution, it can be anything. This is case sensitive. +The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value. - Required: No - Type: string -- Default: `'OMSGallery'` -### Parameter: `publisher` +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` -The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`. +### Parameter: `location` + +Location for all resources. - Required: No - Type: string -- Default: `'Microsoft'` +- Default: `[resourceGroup().location]` ## Outputs diff --git a/avm/res/operations-management/solution/main.bicep b/avm/res/operations-management/solution/main.bicep index 3a98c1a92f..cfe628cad7 100644 --- a/avm/res/operations-management/solution/main.bicep +++ b/avm/res/operations-management/solution/main.bicep @@ -2,21 +2,21 @@ metadata name = 'Operations Management Solutions' metadata description = 'This module deploys an Operations Management Solution.' metadata owner = 'Azure/module-maintainers' -@description('Required. Name of the solution. For Microsoft published gallery solution the target solution resource name will be composed as `{name}({logAnalyticsWorkspaceName})`.') +@description('''Required. Name of the solution. +For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`. +For solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`. +The solution type is case-sensitive.''') param name string +@description('Required. Plan for solution object supported by the OperationsManagement resource provider.') +param plan solutionPlanType + @description('Required. Name of the Log Analytics workspace where the solution will be deployed/enabled.') param logAnalyticsWorkspaceName string @description('Optional. Location for all resources.') param location string = resourceGroup().location -@description('Optional. The product of the deployed solution. For Microsoft published gallery solution it should be `OMSGallery` and the target solution resource product will be composed as `OMSGallery/{name}`. For third party solution, it can be anything. This is case sensitive.') -param product string = 'OMSGallery' - -@description('Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`.') -param publisher string = 'Microsoft' - @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true @@ -43,21 +43,17 @@ resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06 name: logAnalyticsWorkspaceName } -var solutionName = publisher == 'Microsoft' ? '${name}(${logAnalyticsWorkspace.name})' : name - -var solutionProduct = publisher == 'Microsoft' ? 'OMSGallery/${name}' : product - resource solution 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' = { - name: solutionName + name: name location: location properties: { workspaceResourceId: logAnalyticsWorkspace.id } plan: { - name: solutionName + name: plan.?name ?? name promotionCode: '' - product: solutionProduct - publisher: publisher + product: plan.product + publisher: plan.?publisher ?? 'Microsoft' } } @@ -72,3 +68,26 @@ output resourceGroupName string = resourceGroup().name @description('The location the resource was deployed into.') output location string = solution.location + +// =============== // +// Definitions // +// =============== // + +@export() +type solutionPlanType = { + @description('''Optional. Name of the solution to be created. + For solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`. + For solutions authored by third parties, it can be anything. + The solution type is case-sensitive. + If not provided, the value of the `name` parameter will be used.''') + name: string? + + @description('''Required. The product name of the deployed solution. + For Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`. + For a third party solution, it can be anything. + This is case sensitive.''') + product: string + + @description('Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value.') + publisher: string? +} diff --git a/avm/res/operations-management/solution/main.json b/avm/res/operations-management/solution/main.json index 4153919039..91a3ab0d52 100644 --- a/avm/res/operations-management/solution/main.json +++ b/avm/res/operations-management/solution/main.json @@ -1,21 +1,58 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "13605710277319315849" + "version": "0.30.23.60470", + "templateHash": "787568686333677059" }, "name": "Operations Management Solutions", "description": "This module deploys an Operations Management Solution.", "owner": "Azure/module-maintainers" }, + "definitions": { + "solutionPlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the solution to be created.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, it can be anything.\nThe solution type is case-sensitive.\nIf not provided, the value of the `name` parameter will be used." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product name of the deployed solution.\nFor Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.\nFor a third party solution, it can be anything.\nThis is case sensitive." + } + }, + "publisher": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", "metadata": { - "description": "Required. Name of the solution. For Microsoft published gallery solution the target solution resource name will be composed as `{name}({logAnalyticsWorkspaceName})`." + "description": "Required. Name of the solution.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.\nThe solution type is case-sensitive." + } + }, + "plan": { + "$ref": "#/definitions/solutionPlanType", + "metadata": { + "description": "Required. Plan for solution object supported by the OperationsManagement resource provider." } }, "logAnalyticsWorkspaceName": { @@ -31,20 +68,6 @@ "description": "Optional. Location for all resources." } }, - "product": { - "type": "string", - "defaultValue": "OMSGallery", - "metadata": { - "description": "Optional. The product of the deployed solution. For Microsoft published gallery solution it should be `OMSGallery` and the target solution resource product will be composed as `OMSGallery/{name}`. For third party solution, it can be anything. This is case sensitive." - } - }, - "publisher": { - "type": "string", - "defaultValue": "Microsoft", - "metadata": { - "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`." - } - }, "enableTelemetry": { "type": "bool", "defaultValue": true, @@ -53,12 +76,8 @@ } } }, - "variables": { - "solutionName": "[if(equals(parameters('publisher'), 'Microsoft'), format('{0}({1})', parameters('name'), parameters('logAnalyticsWorkspaceName')), parameters('name'))]", - "solutionProduct": "[if(equals(parameters('publisher'), 'Microsoft'), format('OMSGallery/{0}', parameters('name')), parameters('product'))]" - }, - "resources": [ - { + "resources": { + "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", @@ -78,36 +97,45 @@ } } }, - { + "logAnalyticsWorkspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2021-06-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "solution": { "type": "Microsoft.OperationsManagement/solutions", "apiVersion": "2015-11-01-preview", - "name": "[variables('solutionName')]", + "name": "[parameters('name')]", "location": "[parameters('location')]", "properties": { "workspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]" }, "plan": { - "name": "[variables('solutionName')]", + "name": "[coalesce(tryGet(parameters('plan'), 'name'), parameters('name'))]", "promotionCode": "", - "product": "[variables('solutionProduct')]", - "publisher": "[parameters('publisher')]" - } + "product": "[parameters('plan').product]", + "publisher": "[coalesce(tryGet(parameters('plan'), 'publisher'), 'Microsoft')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] } - ], + }, "outputs": { "name": { "type": "string", "metadata": { "description": "The name of the deployed solution." }, - "value": "[variables('solutionName')]" + "value": "[parameters('name')]" }, "resourceId": { "type": "string", "metadata": { "description": "The resource ID of the deployed solution." }, - "value": "[resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName'))]" + "value": "[resourceId('Microsoft.OperationsManagement/solutions', parameters('name'))]" }, "resourceGroupName": { "type": "string", @@ -121,7 +149,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName')), '2015-11-01-preview', 'full').location]" + "value": "[reference('solution', '2015-11-01-preview', 'full').location]" } } } \ No newline at end of file diff --git a/avm/res/operations-management/solution/tests/e2e/defaults/main.test.bicep b/avm/res/operations-management/solution/tests/e2e/defaults/main.test.bicep index 8be0e169ad..ce2cc0cec8 100644 --- a/avm/res/operations-management/solution/tests/e2e/defaults/main.test.bicep +++ b/avm/res/operations-management/solution/tests/e2e/defaults/main.test.bicep @@ -48,7 +48,10 @@ module testDeployment '../../../main.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}' params: { - name: 'Updates' + name: 'Updates(${nestedDependencies.outputs.logAnalyticsWorkspaceName})' + plan: { + product: 'OMSGallery/Updates' + } location: resourceLocation logAnalyticsWorkspaceName: nestedDependencies.outputs.logAnalyticsWorkspaceName } diff --git a/avm/res/operations-management/solution/tests/e2e/ms/main.test.bicep b/avm/res/operations-management/solution/tests/e2e/ms/main.test.bicep index 314aae1901..66af8a8ab1 100644 --- a/avm/res/operations-management/solution/tests/e2e/ms/main.test.bicep +++ b/avm/res/operations-management/solution/tests/e2e/ms/main.test.bicep @@ -48,10 +48,11 @@ module testDeployment '../../../main.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}' params: { - name: 'AzureAutomation' + name: 'AzureAutomation(${nestedDependencies.outputs.logAnalyticsWorkspaceName})' location: resourceLocation logAnalyticsWorkspaceName: nestedDependencies.outputs.logAnalyticsWorkspaceName - product: 'OMSGallery' - publisher: 'Microsoft' + plan: { + product: 'OMSGallery/AzureAutomation' + } } } diff --git a/avm/res/operations-management/solution/tests/e2e/nonms/main.test.bicep b/avm/res/operations-management/solution/tests/e2e/nonms/main.test.bicep index c5211d6040..97a79ad525 100644 --- a/avm/res/operations-management/solution/tests/e2e/nonms/main.test.bicep +++ b/avm/res/operations-management/solution/tests/e2e/nonms/main.test.bicep @@ -51,7 +51,10 @@ module testDeployment '../../../main.bicep' = { name: '${namePrefix}${serviceShort}001' location: resourceLocation logAnalyticsWorkspaceName: nestedDependencies.outputs.logAnalyticsWorkspaceName - product: 'nonmsTestSolutionProduct' - publisher: 'nonmsTestSolutionPublisher' + plan: { + name: 'nonmsTestSolutionPlan' + product: 'nonmsTestSolutionProduct' + publisher: 'nonmsTestSolutionPublisher' + } } } diff --git a/avm/res/operations-management/solution/tests/e2e/sql-auditing/dependencies.bicep b/avm/res/operations-management/solution/tests/e2e/sql-auditing/dependencies.bicep new file mode 100644 index 0000000000..ef3592fb5f --- /dev/null +++ b/avm/res/operations-management/solution/tests/e2e/sql-auditing/dependencies.bicep @@ -0,0 +1,13 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Log Analytics Workspace to create.') +param logAnalyticsWorkspaceName string + +resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-06-01' = { + name: logAnalyticsWorkspaceName + location: location +} + +@description('The name of the created Log Analytics Workspace.') +output logAnalyticsWorkspaceName string = logAnalytics.name diff --git a/avm/res/operations-management/solution/tests/e2e/sql-auditing/main.test.bicep b/avm/res/operations-management/solution/tests/e2e/sql-auditing/main.test.bicep new file mode 100644 index 0000000000..881e251f49 --- /dev/null +++ b/avm/res/operations-management/solution/tests/e2e/sql-auditing/main.test.bicep @@ -0,0 +1,59 @@ +targetScope = 'subscription' + +metadata name = 'SQLAuditing solution' +metadata description = 'This instance deploys the module with the SQLAuditing solution. This solution is authored by Microsoft, but uses a non-standard value for the `product` parameter.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-operationsmanagement.solutions-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'omssqa' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}' + params: { + name: 'SQLAuditing(${nestedDependencies.outputs.logAnalyticsWorkspaceName})' + location: resourceLocation + logAnalyticsWorkspaceName: nestedDependencies.outputs.logAnalyticsWorkspaceName + plan: { + product: 'SQLAuditing' + publisher: 'Microsoft' + } + } +} diff --git a/avm/res/operations-management/solution/tests/e2e/waf-aligned/main.test.bicep b/avm/res/operations-management/solution/tests/e2e/waf-aligned/main.test.bicep index 606797373d..0d5167193e 100644 --- a/avm/res/operations-management/solution/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/operations-management/solution/tests/e2e/waf-aligned/main.test.bicep @@ -50,11 +50,14 @@ module testDeployment '../../../main.bicep' = [ scope: resourceGroup name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' params: { - name: 'AzureAutomation' + name: 'AzureAutomation(${nestedDependencies.outputs.logAnalyticsWorkspaceName})' location: resourceLocation logAnalyticsWorkspaceName: nestedDependencies.outputs.logAnalyticsWorkspaceName - product: 'OMSGallery' - publisher: 'Microsoft' + plan: { + name: 'AzureAutomation(${nestedDependencies.outputs.logAnalyticsWorkspaceName})' + product: 'OMSGallery/AzureAutomation' + publisher: 'Microsoft' + } } } ] diff --git a/avm/res/operations-management/solution/version.json b/avm/res/operations-management/solution/version.json index 83083db694..17dd49a0b9 100644 --- a/avm/res/operations-management/solution/version.json +++ b/avm/res/operations-management/solution/version.json @@ -1,7 +1,7 @@ { - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", - "pathFilters": [ - "./main.json" - ] -} \ No newline at end of file + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.3", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/purview/account/README.md b/avm/res/purview/account/README.md index 7585844571..1abd9cda78 100644 --- a/avm/res/purview/account/README.md +++ b/avm/res/purview/account/README.md @@ -1078,15 +1078,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-accountprivateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-accountprivateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `accountPrivateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-accountprivateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `accountPrivateEndpoints.customDnsConfigs.ipAddresses` @@ -1095,6 +1093,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `accountPrivateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `accountPrivateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -1309,6 +1314,17 @@ Array of role assignments to create. - Required: No - Type: array +- Roles configurable by name: + - `'Contributor'` + - `'DNS Resolver Contributor'` + - `'DNS Zone Contributor'` + - `'Domain Services Contributor'` + - `'Domain Services Reader'` + - `'Network Contributor'` + - `'Owner'` + - `'Private DNS Zone Contributor'` + - `'Reader'` + - `'Role Based Access Control Administrator (Preview)'` **Required parameters** @@ -1627,15 +1643,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-eventhubprivateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-eventhubprivateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `eventHubPrivateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-eventhubprivateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `eventHubPrivateEndpoints.customDnsConfigs.ipAddresses` @@ -1644,6 +1658,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `eventHubPrivateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `eventHubPrivateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -1858,6 +1879,17 @@ Array of role assignments to create. - Required: No - Type: array +- Roles configurable by name: + - `'Contributor'` + - `'DNS Resolver Contributor'` + - `'DNS Zone Contributor'` + - `'Domain Services Contributor'` + - `'Domain Services Reader'` + - `'Network Contributor'` + - `'Owner'` + - `'Private DNS Zone Contributor'` + - `'Reader'` + - `'Role Based Access Control Administrator (Preview)'` **Required parameters** @@ -2018,13 +2050,13 @@ The managed identity definition for this resource. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | ### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. -- Required: Yes +- Required: No - Type: array ### Parameter: `managedResourceGroupName` @@ -2094,15 +2126,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-portalprivateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-portalprivateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `portalPrivateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-portalprivateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `portalPrivateEndpoints.customDnsConfigs.ipAddresses` @@ -2111,6 +2141,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `portalPrivateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `portalPrivateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -2325,6 +2362,17 @@ Array of role assignments to create. - Required: No - Type: array +- Roles configurable by name: + - `'Contributor'` + - `'DNS Resolver Contributor'` + - `'DNS Zone Contributor'` + - `'Domain Services Contributor'` + - `'Domain Services Reader'` + - `'Network Contributor'` + - `'Owner'` + - `'Private DNS Zone Contributor'` + - `'Reader'` + - `'Role Based Access Control Administrator (Preview)'` **Required parameters** @@ -2608,15 +2656,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-storageblobprivateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-storageblobprivateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `storageBlobPrivateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-storageblobprivateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `storageBlobPrivateEndpoints.customDnsConfigs.ipAddresses` @@ -2625,6 +2671,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `storageBlobPrivateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `storageBlobPrivateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -2841,10 +2894,15 @@ Array of role assignments to create. - Type: array - Roles configurable by name: - `'Contributor'` + - `'DNS Resolver Contributor'` + - `'DNS Zone Contributor'` + - `'Domain Services Contributor'` + - `'Domain Services Reader'` + - `'Network Contributor'` - `'Owner'` + - `'Private DNS Zone Contributor'` - `'Reader'` - - `'Role Based Access Control Administrator'` - - `'User Access Administrator'` + - `'Role Based Access Control Administrator (Preview)'` **Required parameters** @@ -3009,15 +3067,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-storagequeueprivateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-storagequeueprivateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `storageQueuePrivateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-storagequeueprivateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `storageQueuePrivateEndpoints.customDnsConfigs.ipAddresses` @@ -3026,6 +3082,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `storageQueuePrivateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `storageQueuePrivateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -3242,10 +3305,15 @@ Array of role assignments to create. - Type: array - Roles configurable by name: - `'Contributor'` + - `'DNS Resolver Contributor'` + - `'DNS Zone Contributor'` + - `'Domain Services Contributor'` + - `'Domain Services Reader'` + - `'Network Contributor'` - `'Owner'` + - `'Private DNS Zone Contributor'` - `'Reader'` - - `'Role Based Access Control Administrator'` - - `'User Access Administrator'` + - `'Role Based Access Control Administrator (Preview)'` **Required parameters** @@ -3384,6 +3452,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/purview/account/main.bicep b/avm/res/purview/account/main.bicep index e0d408fdb1..e3ec79f296 100644 --- a/avm/res/purview/account/main.bicep +++ b/avm/res/purview/account/main.bicep @@ -13,8 +13,9 @@ param location string = resourceGroup().location @description('Optional. Tags of the resource.') param tags object? +import { managedIdentityOnlyUserAssignedType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityOnlyUserAssignedType? @description('Optional. The Managed Resource Group Name. A managed Storage Account, and an Event Hubs will be created in the selected subscription for catalog ingestion scenarios. Default is \'managed-rg-\'.') param managedResourceGroupName string = 'managed-rg-${name}' @@ -165,7 +166,7 @@ resource account_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021- } ] -module account_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ +module account_accountPrivateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ for (privateEndpoint, index) in (accountPrivateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-account-PrivateEndpoint-${index}' scope: resourceGroup(privateEndpoint.?resourceGroupName ?? '') @@ -217,7 +218,7 @@ module account_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7. } ] -module portal_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ +module account_portalPrivateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ for (privateEndpoint, index) in (portalPrivateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-portal-PrivateEndpoint-${index}' scope: resourceGroup(privateEndpoint.?resourceGroupName ?? '') @@ -269,7 +270,7 @@ module portal_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1 } ] -module blob_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ +module account_storageBlobPrivateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ for (privateEndpoint, index) in (storageBlobPrivateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-blob-PrivateEndpoint-${index}' scope: resourceGroup(privateEndpoint.?resourceGroupName ?? '') @@ -321,7 +322,7 @@ module blob_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' } ] -module queue_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ +module account_storageQueuePrivateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ for (privateEndpoint, index) in (storageQueuePrivateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-queue-PrivateEndpoint-${index}' scope: resourceGroup(privateEndpoint.?resourceGroupName ?? '') @@ -373,7 +374,7 @@ module queue_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' } ] -module eventHub_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ +module account_eventHubPrivateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ for (privateEndpoint, index) in (eventHubPrivateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-eventHub-PrivateEndpoint-${index}' scope: resourceGroup(privateEndpoint.?resourceGroupName ?? '') @@ -471,55 +472,55 @@ output systemAssignedMIPrincipalId string = account.?identity.?principalId ?? '' @description('The private endpoints of the Purview Account.') output accountPrivateEndpoints array = [ for (pe, i) in (!empty(accountPrivateEndpoints) ? array(accountPrivateEndpoints) : []): { - name: account_privateEndpoints[i].outputs.name - resourceId: account_privateEndpoints[i].outputs.resourceId - groupId: account_privateEndpoints[i].outputs.groupId - customDnsConfig: account_privateEndpoints[i].outputs.customDnsConfig - networkInterfaceIds: account_privateEndpoints[i].outputs.networkInterfaceIds + name: account_accountPrivateEndpoints[i].outputs.name + resourceId: account_accountPrivateEndpoints[i].outputs.resourceId + groupId: account_accountPrivateEndpoints[i].outputs.groupId + customDnsConfig: account_accountPrivateEndpoints[i].outputs.customDnsConfig + networkInterfaceIds: account_accountPrivateEndpoints[i].outputs.networkInterfaceIds } ] @description('The private endpoints of the Purview Account Portal.') output portalPrivateEndpoints array = [ for (pe, i) in (!empty(portalPrivateEndpoints) ? array(portalPrivateEndpoints) : []): { - name: portal_privateEndpoints[i].outputs.name - resourceId: portal_privateEndpoints[i].outputs.resourceId - groupId: portal_privateEndpoints[i].outputs.groupId - customDnsConfig: portal_privateEndpoints[i].outputs.customDnsConfig - networkInterfaceIds: portal_privateEndpoints[i].outputs.networkInterfaceIds + name: account_portalPrivateEndpoints[i].outputs.name + resourceId: account_portalPrivateEndpoints[i].outputs.resourceId + groupId: account_portalPrivateEndpoints[i].outputs.groupId + customDnsConfig: account_portalPrivateEndpoints[i].outputs.customDnsConfig + networkInterfaceIds: account_portalPrivateEndpoints[i].outputs.networkInterfaceIds } ] @description('The private endpoints of the managed storage account blob service.') output storageBlobPrivateEndpoints array = [ for (pe, i) in (!empty(storageBlobPrivateEndpoints) ? array(storageBlobPrivateEndpoints) : []): { - name: blob_privateEndpoints[i].outputs.name - resourceId: blob_privateEndpoints[i].outputs.resourceId - groupId: blob_privateEndpoints[i].outputs.groupId - customDnsConfig: blob_privateEndpoints[i].outputs.customDnsConfig - networkInterfaceIds: blob_privateEndpoints[i].outputs.networkInterfaceIds + name: account_storageBlobPrivateEndpoints[i].outputs.name + resourceId: account_storageBlobPrivateEndpoints[i].outputs.resourceId + groupId: account_storageBlobPrivateEndpoints[i].outputs.groupId + customDnsConfig: account_storageBlobPrivateEndpoints[i].outputs.customDnsConfig + networkInterfaceIds: account_storageBlobPrivateEndpoints[i].outputs.networkInterfaceIds } ] @description('The private endpoints of the managed storage account queue service.') output storageQueuePrivateEndpoints array = [ for (pe, i) in (!empty(storageQueuePrivateEndpoints) ? array(storageQueuePrivateEndpoints) : []): { - name: queue_privateEndpoints[i].outputs.name - resourceId: queue_privateEndpoints[i].outputs.resourceId - groupId: queue_privateEndpoints[i].outputs.groupId - customDnsConfig: queue_privateEndpoints[i].outputs.customDnsConfig - networkInterfaceIds: queue_privateEndpoints[i].outputs.networkInterfaceIds + name: account_storageQueuePrivateEndpoints[i].outputs.name + resourceId: account_storageQueuePrivateEndpoints[i].outputs.resourceId + groupId: account_storageQueuePrivateEndpoints[i].outputs.groupId + customDnsConfig: account_storageQueuePrivateEndpoints[i].outputs.customDnsConfig + networkInterfaceIds: account_storageQueuePrivateEndpoints[i].outputs.networkInterfaceIds } ] @description('The private endpoints of the managed Event Hub Namespace.') output eventHubPrivateEndpoints array = [ for (pe, i) in (!empty(eventHubPrivateEndpoints) ? array(eventHubPrivateEndpoints) : []): { - name: eventHub_privateEndpoints[i].outputs.name - resourceId: eventHub_privateEndpoints[i].outputs.resourceId - groupId: eventHub_privateEndpoints[i].outputs.groupId - customDnsConfig: eventHub_privateEndpoints[i].outputs.customDnsConfig - networkInterfaceIds: eventHub_privateEndpoints[i].outputs.networkInterfaceIds + name: account_eventHubPrivateEndpoints[i].outputs.name + resourceId: account_eventHubPrivateEndpoints[i].outputs.resourceId + groupId: account_eventHubPrivateEndpoints[i].outputs.groupId + customDnsConfig: account_eventHubPrivateEndpoints[i].outputs.customDnsConfig + networkInterfaceIds: account_eventHubPrivateEndpoints[i].outputs.networkInterfaceIds } ] @@ -527,11 +528,6 @@ output eventHubPrivateEndpoints array = [ // Definitions // // =============== // -type managedIdentitiesType = { - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[] -}? - type lockType = { @description('Optional. Specify the name of lock.') name: string? @@ -650,7 +646,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/purview/account/main.json b/avm/res/purview/account/main.json index 34bd78df71..20e38c94f8 100644 --- a/avm/res/purview/account/main.json +++ b/avm/res/purview/account/main.json @@ -5,29 +5,14 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "14495497067965615328" + "version": "0.30.23.60470", + "templateHash": "6120060466877826337" }, "name": "Purview Accounts", "description": "This module deploys a Purview Account.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { - "type": "object", - "properties": { - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." - } - } - }, - "nullable": true - }, "lockType": { "type": "object", "properties": { @@ -349,7 +334,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -465,6 +450,27 @@ } }, "nullable": true + }, + "managedIdentityOnlyUserAssignedType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -491,7 +497,8 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityOnlyUserAssignedType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } @@ -703,9 +710,9 @@ "account" ] }, - "account_privateEndpoints": { + "account_accountPrivateEndpoints": { "copy": { - "name": "account_privateEndpoints", + "name": "account_accountPrivateEndpoints", "count": "[length(coalesce(parameters('accountPrivateEndpoints'), createArray()))]" }, "type": "Microsoft.Resources/deployments", @@ -1469,9 +1476,9 @@ "account" ] }, - "portal_privateEndpoints": { + "account_portalPrivateEndpoints": { "copy": { - "name": "portal_privateEndpoints", + "name": "account_portalPrivateEndpoints", "count": "[length(coalesce(parameters('portalPrivateEndpoints'), createArray()))]" }, "type": "Microsoft.Resources/deployments", @@ -2235,9 +2242,9 @@ "account" ] }, - "blob_privateEndpoints": { + "account_storageBlobPrivateEndpoints": { "copy": { - "name": "blob_privateEndpoints", + "name": "account_storageBlobPrivateEndpoints", "count": "[length(coalesce(parameters('storageBlobPrivateEndpoints'), createArray()))]" }, "type": "Microsoft.Resources/deployments", @@ -3001,9 +3008,9 @@ "account" ] }, - "queue_privateEndpoints": { + "account_storageQueuePrivateEndpoints": { "copy": { - "name": "queue_privateEndpoints", + "name": "account_storageQueuePrivateEndpoints", "count": "[length(coalesce(parameters('storageQueuePrivateEndpoints'), createArray()))]" }, "type": "Microsoft.Resources/deployments", @@ -3767,9 +3774,9 @@ "account" ] }, - "eventHub_privateEndpoints": { + "account_eventHubPrivateEndpoints": { "copy": { - "name": "eventHub_privateEndpoints", + "name": "account_eventHubPrivateEndpoints", "count": "[length(coalesce(parameters('eventHubPrivateEndpoints'), createArray()))]" }, "type": "Microsoft.Resources/deployments", @@ -4606,11 +4613,11 @@ "copy": { "count": "[length(if(not(empty(parameters('accountPrivateEndpoints'))), array(parameters('accountPrivateEndpoints')), createArray()))]", "input": { - "name": "[reference(format('account_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", - "resourceId": "[reference(format('account_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", - "groupId": "[reference(format('account_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", - "customDnsConfig": "[reference(format('account_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", - "networkInterfaceIds": "[reference(format('account_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + "name": "[reference(format('account_accountPrivateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('account_accountPrivateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('account_accountPrivateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('account_accountPrivateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('account_accountPrivateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" } } }, @@ -4622,11 +4629,11 @@ "copy": { "count": "[length(if(not(empty(parameters('portalPrivateEndpoints'))), array(parameters('portalPrivateEndpoints')), createArray()))]", "input": { - "name": "[reference(format('portal_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", - "resourceId": "[reference(format('portal_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", - "groupId": "[reference(format('portal_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", - "customDnsConfig": "[reference(format('portal_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", - "networkInterfaceIds": "[reference(format('portal_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + "name": "[reference(format('account_portalPrivateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('account_portalPrivateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('account_portalPrivateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('account_portalPrivateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('account_portalPrivateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" } } }, @@ -4638,11 +4645,11 @@ "copy": { "count": "[length(if(not(empty(parameters('storageBlobPrivateEndpoints'))), array(parameters('storageBlobPrivateEndpoints')), createArray()))]", "input": { - "name": "[reference(format('blob_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", - "resourceId": "[reference(format('blob_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", - "groupId": "[reference(format('blob_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", - "customDnsConfig": "[reference(format('blob_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", - "networkInterfaceIds": "[reference(format('blob_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + "name": "[reference(format('account_storageBlobPrivateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('account_storageBlobPrivateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('account_storageBlobPrivateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('account_storageBlobPrivateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('account_storageBlobPrivateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" } } }, @@ -4654,11 +4661,11 @@ "copy": { "count": "[length(if(not(empty(parameters('storageQueuePrivateEndpoints'))), array(parameters('storageQueuePrivateEndpoints')), createArray()))]", "input": { - "name": "[reference(format('queue_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", - "resourceId": "[reference(format('queue_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", - "groupId": "[reference(format('queue_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", - "customDnsConfig": "[reference(format('queue_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", - "networkInterfaceIds": "[reference(format('queue_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + "name": "[reference(format('account_storageQueuePrivateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('account_storageQueuePrivateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('account_storageQueuePrivateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('account_storageQueuePrivateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('account_storageQueuePrivateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" } } }, @@ -4670,11 +4677,11 @@ "copy": { "count": "[length(if(not(empty(parameters('eventHubPrivateEndpoints'))), array(parameters('eventHubPrivateEndpoints')), createArray()))]", "input": { - "name": "[reference(format('eventHub_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", - "resourceId": "[reference(format('eventHub_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", - "groupId": "[reference(format('eventHub_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", - "customDnsConfig": "[reference(format('eventHub_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", - "networkInterfaceIds": "[reference(format('eventHub_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + "name": "[reference(format('account_eventHubPrivateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('account_eventHubPrivateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('account_eventHubPrivateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('account_eventHubPrivateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('account_eventHubPrivateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" } } } diff --git a/avm/res/recovery-services/vault/README.md b/avm/res/recovery-services/vault/README.md index 65477a4986..e9ade080e0 100644 --- a/avm/res/recovery-services/vault/README.md +++ b/avm/res/recovery-services/vault/README.md @@ -3061,15 +3061,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -3078,6 +3076,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/recovery-services/vault/backup-config/main.json b/avm/res/recovery-services/vault/backup-config/main.json index acb2cb784e..cea379ce42 100644 --- a/avm/res/recovery-services/vault/backup-config/main.json +++ b/avm/res/recovery-services/vault/backup-config/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "16706009499329717813" + "version": "0.30.23.60470", + "templateHash": "11104609825546301514" }, "name": "Recovery Services Vault Backup Config", "description": "This module deploys a Recovery Services Vault Backup Config.", diff --git a/avm/res/recovery-services/vault/backup-fabric/protection-container/main.json b/avm/res/recovery-services/vault/backup-fabric/protection-container/main.json index b85b737445..10c19edb29 100644 --- a/avm/res/recovery-services/vault/backup-fabric/protection-container/main.json +++ b/avm/res/recovery-services/vault/backup-fabric/protection-container/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7107776981403889232" + "version": "0.30.23.60470", + "templateHash": "3738002202831366506" }, "name": "Recovery Services Vault Protection Container", "description": "This module deploys a Recovery Services Vault Protection Container.", @@ -144,8 +144,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4676289166883418684" + "version": "0.30.23.60470", + "templateHash": "12193073774274736616" }, "name": "Recovery Service Vaults Protection Container Protected Item", "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", diff --git a/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.json b/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.json index f337cc9f66..9aa95b7b17 100644 --- a/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.json +++ b/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4676289166883418684" + "version": "0.30.23.60470", + "templateHash": "12193073774274736616" }, "name": "Recovery Service Vaults Protection Container Protected Item", "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", diff --git a/avm/res/recovery-services/vault/backup-policy/main.json b/avm/res/recovery-services/vault/backup-policy/main.json index 64efc19007..44dc4765ba 100644 --- a/avm/res/recovery-services/vault/backup-policy/main.json +++ b/avm/res/recovery-services/vault/backup-policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "3484552475575852642" + "version": "0.30.23.60470", + "templateHash": "2997233827023702889" }, "name": "Recovery Services Vault Backup Policies", "description": "This module deploys a Recovery Services Vault Backup Policy.", diff --git a/avm/res/recovery-services/vault/backup-storage-config/main.json b/avm/res/recovery-services/vault/backup-storage-config/main.json index d4257df69b..2fad6d1a98 100644 --- a/avm/res/recovery-services/vault/backup-storage-config/main.json +++ b/avm/res/recovery-services/vault/backup-storage-config/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15771571961904697298" + "version": "0.30.23.60470", + "templateHash": "8831096651733297926" }, "name": "Recovery Services Vault Backup Storage Config", "description": "This module deploys a Recovery Service Vault Backup Storage Configuration.", diff --git a/avm/res/recovery-services/vault/main.bicep b/avm/res/recovery-services/vault/main.bicep index 6f984370b8..49a85c68b8 100644 --- a/avm/res/recovery-services/vault/main.bicep +++ b/avm/res/recovery-services/vault/main.bicep @@ -493,7 +493,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/recovery-services/vault/main.json b/avm/res/recovery-services/vault/main.json index f05335967c..edda40c893 100644 --- a/avm/res/recovery-services/vault/main.json +++ b/avm/res/recovery-services/vault/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11169688111946598929" + "version": "0.30.23.60470", + "templateHash": "1168094723641222476" }, "name": "Recovery Services Vaults", "description": "This module deploys a Recovery Services Vault.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -776,8 +776,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "14351620305513283067" + "version": "0.30.23.60470", + "templateHash": "16298384162352496224" }, "name": "Recovery Services Vault Replication Fabrics", "description": "This module deploys a Replication Fabric for Azure to Azure disaster recovery scenario of Azure Site Recovery.\n\n> Note: this module currently support only the `instanceType: 'Azure'` scenario.", @@ -794,7 +794,7 @@ "type": "string", "defaultValue": "[resourceGroup().location]", "metadata": { - "description": "Required. The recovery location the fabric represents." + "description": "Optional. The recovery location the fabric represents." } }, "name": { @@ -847,7 +847,9 @@ "replicationFabricName": { "value": "[parameters('name')]" }, - "replicationContainerMappings": "[if(contains(parameters('replicationContainers')[copyIndex()], 'replicationContainerMappings'), createObject('value', parameters('replicationContainers')[copyIndex()].replicationContainerMappings), createObject('value', createArray()))]" + "replicationContainerMappings": { + "value": "[tryGet(parameters('replicationContainers')[copyIndex()], 'replicationContainerMappings')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -855,8 +857,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10179392610574660553" + "version": "0.30.23.60470", + "templateHash": "17558710415740898922" }, "name": "Recovery Services Vault Replication Fabric Replication Protection Containers", "description": "This module deploys a Recovery Services Vault Replication Protection Container.\n\n> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.", @@ -916,9 +918,15 @@ }, "mode": "Incremental", "parameters": { - "name": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'name'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].name), createObject('value', ''))]", - "policyId": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'policyId'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].policyId), createObject('value', ''))]", - "policyName": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'policyName'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].policyName), createObject('value', ''))]", + "name": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'name')]" + }, + "policyId": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'policyId')]" + }, + "policyName": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'policyName')]" + }, "recoveryVaultName": { "value": "[parameters('recoveryVaultName')]" }, @@ -928,9 +936,15 @@ "sourceProtectionContainerName": { "value": "[parameters('name')]" }, - "targetProtectionContainerId": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'targetProtectionContainerId'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].targetProtectionContainerId), createObject('value', ''))]", - "targetContainerFabricName": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerFabricName'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].targetContainerFabricName), createObject('value', parameters('replicationFabricName')))]", - "targetContainerName": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerName'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].targetContainerName), createObject('value', ''))]" + "targetProtectionContainerId": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'targetProtectionContainerId')]" + }, + "targetContainerFabricName": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerFabricName')]" + }, + "targetContainerName": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerName')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -938,8 +952,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9091386051733041821" + "version": "0.30.23.60470", + "templateHash": "5738551771802324865" }, "name": "Recovery Services Vault Replication Fabric Replication Protection Container Replication Protection Container Mappings", "description": "This module deploys a Recovery Services Vault (RSV) Replication Protection Container Mapping.\n\n> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.", @@ -1147,8 +1161,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "14083088922027127333" + "version": "0.30.23.60470", + "templateHash": "15732147582012031147" }, "name": "Recovery Services Vault Replication Policies", "description": "This module deploys a Recovery Services Vault Replication Policy for Disaster Recovery scenario.\n\n> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.", @@ -1272,8 +1286,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15771571961904697298" + "version": "0.30.23.60470", + "templateHash": "8831096651733297926" }, "name": "Recovery Services Vault Backup Storage Config", "description": "This module deploys a Recovery Service Vault Backup Storage Configuration.", @@ -1398,8 +1412,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7107776981403889232" + "version": "0.30.23.60470", + "templateHash": "3738002202831366506" }, "name": "Recovery Services Vault Protection Container", "description": "This module deploys a Recovery Services Vault Protection Container.", @@ -1537,8 +1551,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4676289166883418684" + "version": "0.30.23.60470", + "templateHash": "12193073774274736616" }, "name": "Recovery Service Vaults Protection Container Protected Item", "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", @@ -1703,8 +1717,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "3484552475575852642" + "version": "0.30.23.60470", + "templateHash": "2997233827023702889" }, "name": "Recovery Services Vault Backup Policies", "description": "This module deploys a Recovery Services Vault Backup Policy.", @@ -1796,8 +1810,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "16706009499329717813" + "version": "0.30.23.60470", + "templateHash": "11104609825546301514" }, "name": "Recovery Services Vault Backup Config", "description": "This module deploys a Recovery Services Vault Backup Config.", @@ -1963,8 +1977,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "14356935491527849801" + "version": "0.30.23.60470", + "templateHash": "7857651426193262933" }, "name": "Recovery Services Vault Replication Alert Settings", "description": "This module deploys a Recovery Services Vault Replication Alert Settings.", diff --git a/avm/res/recovery-services/vault/replication-alert-setting/main.json b/avm/res/recovery-services/vault/replication-alert-setting/main.json index ef2755c71e..0ae5a022eb 100644 --- a/avm/res/recovery-services/vault/replication-alert-setting/main.json +++ b/avm/res/recovery-services/vault/replication-alert-setting/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "14356935491527849801" + "version": "0.30.23.60470", + "templateHash": "7857651426193262933" }, "name": "Recovery Services Vault Replication Alert Settings", "description": "This module deploys a Recovery Services Vault Replication Alert Settings.", diff --git a/avm/res/recovery-services/vault/replication-fabric/README.md b/avm/res/recovery-services/vault/replication-fabric/README.md index 26ebf9b2a1..c363361733 100644 --- a/avm/res/recovery-services/vault/replication-fabric/README.md +++ b/avm/res/recovery-services/vault/replication-fabric/README.md @@ -20,12 +20,6 @@ This module deploys a Replication Fabric for Azure to Azure disaster recovery sc ## Parameters -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`location`](#parameter-location) | string | The recovery location the fabric represents. | - **Conditional parameters** | Parameter | Type | Description | @@ -36,23 +30,24 @@ This module deploys a Replication Fabric for Azure to Azure disaster recovery sc | Parameter | Type | Description | | :-- | :-- | :-- | +| [`location`](#parameter-location) | string | The recovery location the fabric represents. | | [`name`](#parameter-name) | string | The name of the fabric. | | [`replicationContainers`](#parameter-replicationcontainers) | array | Replication containers to create. | -### Parameter: `location` +### Parameter: `recoveryVaultName` -The recovery location the fabric represents. +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. -- Required: No +- Required: Yes - Type: string -- Default: `[resourceGroup().location]` -### Parameter: `recoveryVaultName` +### Parameter: `location` -The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. +The recovery location the fabric represents. -- Required: Yes +- Required: No - Type: string +- Default: `[resourceGroup().location]` ### Parameter: `name` diff --git a/avm/res/recovery-services/vault/replication-fabric/main.bicep b/avm/res/recovery-services/vault/replication-fabric/main.bicep index e7b7f91869..180d13b90b 100644 --- a/avm/res/recovery-services/vault/replication-fabric/main.bicep +++ b/avm/res/recovery-services/vault/replication-fabric/main.bicep @@ -7,7 +7,7 @@ metadata owner = 'Azure/module-maintainers' @description('Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment.') param recoveryVaultName string -@description('Required. The recovery location the fabric represents.') +@description('Optional. The recovery location the fabric represents.') param location string = resourceGroup().location @description('Optional. The name of the fabric.') @@ -33,9 +33,7 @@ module fabric_replicationContainers 'replication-protection-container/main.bicep name: container.name recoveryVaultName: recoveryVaultName replicationFabricName: name - replicationContainerMappings: contains(container, 'replicationContainerMappings') - ? container.replicationContainerMappings - : [] + replicationContainerMappings: container.?replicationContainerMappings } dependsOn: [ replicationFabric diff --git a/avm/res/recovery-services/vault/replication-fabric/main.json b/avm/res/recovery-services/vault/replication-fabric/main.json index 62b645b48d..d55ea53bcb 100644 --- a/avm/res/recovery-services/vault/replication-fabric/main.json +++ b/avm/res/recovery-services/vault/replication-fabric/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "14351620305513283067" + "version": "0.30.23.60470", + "templateHash": "16298384162352496224" }, "name": "Recovery Services Vault Replication Fabrics", "description": "This module deploys a Replication Fabric for Azure to Azure disaster recovery scenario of Azure Site Recovery.\n\n> Note: this module currently support only the `instanceType: 'Azure'` scenario.", @@ -22,7 +22,7 @@ "type": "string", "defaultValue": "[resourceGroup().location]", "metadata": { - "description": "Required. The recovery location the fabric represents." + "description": "Optional. The recovery location the fabric represents." } }, "name": { @@ -75,7 +75,9 @@ "replicationFabricName": { "value": "[parameters('name')]" }, - "replicationContainerMappings": "[if(contains(parameters('replicationContainers')[copyIndex()], 'replicationContainerMappings'), createObject('value', parameters('replicationContainers')[copyIndex()].replicationContainerMappings), createObject('value', createArray()))]" + "replicationContainerMappings": { + "value": "[tryGet(parameters('replicationContainers')[copyIndex()], 'replicationContainerMappings')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -83,8 +85,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10179392610574660553" + "version": "0.30.23.60470", + "templateHash": "17558710415740898922" }, "name": "Recovery Services Vault Replication Fabric Replication Protection Containers", "description": "This module deploys a Recovery Services Vault Replication Protection Container.\n\n> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.", @@ -144,9 +146,15 @@ }, "mode": "Incremental", "parameters": { - "name": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'name'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].name), createObject('value', ''))]", - "policyId": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'policyId'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].policyId), createObject('value', ''))]", - "policyName": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'policyName'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].policyName), createObject('value', ''))]", + "name": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'name')]" + }, + "policyId": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'policyId')]" + }, + "policyName": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'policyName')]" + }, "recoveryVaultName": { "value": "[parameters('recoveryVaultName')]" }, @@ -156,9 +164,15 @@ "sourceProtectionContainerName": { "value": "[parameters('name')]" }, - "targetProtectionContainerId": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'targetProtectionContainerId'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].targetProtectionContainerId), createObject('value', ''))]", - "targetContainerFabricName": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerFabricName'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].targetContainerFabricName), createObject('value', parameters('replicationFabricName')))]", - "targetContainerName": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerName'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].targetContainerName), createObject('value', ''))]" + "targetProtectionContainerId": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'targetProtectionContainerId')]" + }, + "targetContainerFabricName": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerFabricName')]" + }, + "targetContainerName": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerName')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -166,8 +180,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9091386051733041821" + "version": "0.30.23.60470", + "templateHash": "5738551771802324865" }, "name": "Recovery Services Vault Replication Fabric Replication Protection Container Replication Protection Container Mappings", "description": "This module deploys a Recovery Services Vault (RSV) Replication Protection Container Mapping.\n\n> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.", diff --git a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.bicep b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.bicep index 95114d9bcb..ca5b907491 100644 --- a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.bicep +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.bicep @@ -31,19 +31,15 @@ module fabric_container_containerMappings 'replication-protection-container-mapp 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 : '' + name: mapping.?name + policyId: mapping.?policyId + 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 : '' + targetProtectionContainerId: mapping.?targetProtectionContainerId + targetContainerFabricName: mapping.?targetContainerFabricName + targetContainerName: mapping.?targetContainerName } dependsOn: [ replicationContainer diff --git a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.json b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.json index 691ec1374c..f6ce642852 100644 --- a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.json +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10179392610574660553" + "version": "0.30.23.60470", + "templateHash": "17558710415740898922" }, "name": "Recovery Services Vault Replication Fabric Replication Protection Containers", "description": "This module deploys a Recovery Services Vault Replication Protection Container.\n\n> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.", @@ -65,9 +65,15 @@ }, "mode": "Incremental", "parameters": { - "name": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'name'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].name), createObject('value', ''))]", - "policyId": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'policyId'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].policyId), createObject('value', ''))]", - "policyName": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'policyName'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].policyName), createObject('value', ''))]", + "name": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'name')]" + }, + "policyId": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'policyId')]" + }, + "policyName": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'policyName')]" + }, "recoveryVaultName": { "value": "[parameters('recoveryVaultName')]" }, @@ -77,9 +83,15 @@ "sourceProtectionContainerName": { "value": "[parameters('name')]" }, - "targetProtectionContainerId": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'targetProtectionContainerId'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].targetProtectionContainerId), createObject('value', ''))]", - "targetContainerFabricName": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerFabricName'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].targetContainerFabricName), createObject('value', parameters('replicationFabricName')))]", - "targetContainerName": "[if(contains(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerName'), createObject('value', parameters('replicationContainerMappings')[copyIndex()].targetContainerName), createObject('value', ''))]" + "targetProtectionContainerId": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'targetProtectionContainerId')]" + }, + "targetContainerFabricName": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerFabricName')]" + }, + "targetContainerName": { + "value": "[tryGet(parameters('replicationContainerMappings')[copyIndex()], 'targetContainerName')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -87,8 +99,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9091386051733041821" + "version": "0.30.23.60470", + "templateHash": "5738551771802324865" }, "name": "Recovery Services Vault Replication Fabric Replication Protection Container Replication Protection Container Mappings", "description": "This module deploys a Recovery Services Vault (RSV) Replication Protection Container Mapping.\n\n> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.", diff --git a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.json b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.json index 211070c849..a3439ebaac 100644 --- a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.json +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9091386051733041821" + "version": "0.30.23.60470", + "templateHash": "5738551771802324865" }, "name": "Recovery Services Vault Replication Fabric Replication Protection Container Replication Protection Container Mappings", "description": "This module deploys a Recovery Services Vault (RSV) Replication Protection Container Mapping.\n\n> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.", diff --git a/avm/res/recovery-services/vault/replication-policy/main.json b/avm/res/recovery-services/vault/replication-policy/main.json index 5e8f6eda48..a2aadac452 100644 --- a/avm/res/recovery-services/vault/replication-policy/main.json +++ b/avm/res/recovery-services/vault/replication-policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "14083088922027127333" + "version": "0.30.23.60470", + "templateHash": "15732147582012031147" }, "name": "Recovery Services Vault Replication Policies", "description": "This module deploys a Recovery Services Vault Replication Policy for Disaster Recovery scenario.\n\n> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.", diff --git a/avm/res/relay/namespace/README.md b/avm/res/relay/namespace/README.md index 4059dd7c06..0470949e3d 100644 --- a/avm/res/relay/namespace/README.md +++ b/avm/res/relay/namespace/README.md @@ -994,7 +994,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -1104,7 +1104,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -1208,22 +1208,22 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the Private Endpoint IP configuration is included. | | [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | -| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the Private Endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. | | [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | -| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the Private Endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | -| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS zone group to configure for the private endpoint. | +| [`name`](#parameter-privateendpointsname) | string | The name of the Private Endpoint. | +| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS Zone Group to configure for the Private Endpoint. | | [`privateLinkServiceConnectionName`](#parameter-privateendpointsprivatelinkserviceconnectionname) | string | The name of the private link connection to create. | -| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. | +| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | -| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/Resource Groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -1234,7 +1234,7 @@ Resource ID of the subnet where the endpoint needs to be created. ### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` -Application security groups in which the private endpoint IP configuration is included. +Application security groups in which the Private Endpoint IP configuration is included. - Required: No - Type: array @@ -1250,15 +1250,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1267,9 +1265,16 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` -The custom name of the network interface attached to the private endpoint. +The custom name of the network interface attached to the Private Endpoint. - Required: No - Type: string @@ -1283,7 +1288,7 @@ Enable/Disable usage telemetry for module. ### Parameter: `privateEndpoints.ipConfigurations` -A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. +A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. - Required: No - Type: array @@ -1347,7 +1352,7 @@ If Manual Private Link Connection is required. ### Parameter: `privateEndpoints.location` -The location to deploy the private endpoint to. +The location to deploy the Private Endpoint to. - Required: No - Type: string @@ -1397,14 +1402,14 @@ A message passed to the owner of the remote resource with the manual connection ### Parameter: `privateEndpoints.name` -The name of the private endpoint. +The name of the Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.privateDnsZoneGroup` -The private DNS zone group to configure for the private endpoint. +The private DNS Zone Group to configure for the Private Endpoint. - Required: No - Type: object @@ -1413,7 +1418,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -1423,7 +1428,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -1438,7 +1443,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -1449,7 +1454,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -1470,7 +1475,7 @@ The name of the private link connection to create. ### Parameter: `privateEndpoints.resourceGroupName` -Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. +Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. - Required: No - Type: string @@ -1585,14 +1590,14 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". +The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.tags` -Tags to be applied on all resources/resource groups in this deployment. +Tags to be applied on all resources/Resource Groups in this deployment. - Required: No - Type: object @@ -1749,6 +1754,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/relay/namespace/authorization-rule/main.json b/avm/res/relay/namespace/authorization-rule/main.json index 1dcf45602b..7862acd2c2 100644 --- a/avm/res/relay/namespace/authorization-rule/main.json +++ b/avm/res/relay/namespace/authorization-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13234316448276715063" + "version": "0.30.23.60470", + "templateHash": "9137586793857005081" }, "name": "Relay Namespace Authorization Rules", "description": "This module deploys a Relay Namespace Authorization Rule.", diff --git a/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.json b/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.json index 01bb4c827b..645ef9e6c1 100644 --- a/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.json +++ b/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11780139902470137859" + "version": "0.30.23.60470", + "templateHash": "4431168643851665214" }, "name": "Hybrid Connection Authorization Rules", "description": "This module deploys a Hybrid Connection Authorization Rule.", diff --git a/avm/res/relay/namespace/hybrid-connection/main.json b/avm/res/relay/namespace/hybrid-connection/main.json index b5807ecc0d..6b8fe5109b 100644 --- a/avm/res/relay/namespace/hybrid-connection/main.json +++ b/avm/res/relay/namespace/hybrid-connection/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "3066452421480890151" + "version": "0.30.23.60470", + "templateHash": "16821503954722419440" }, "name": "Relay Namespace Hybrid Connections", "description": "This module deploys a Relay Namespace Hybrid Connection.", @@ -290,8 +290,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11780139902470137859" + "version": "0.30.23.60470", + "templateHash": "4431168643851665214" }, "name": "Hybrid Connection Authorization Rules", "description": "This module deploys a Hybrid Connection Authorization Rule.", diff --git a/avm/res/relay/namespace/main.bicep b/avm/res/relay/namespace/main.bicep index 9758646370..95847ac31a 100644 --- a/avm/res/relay/namespace/main.bicep +++ b/avm/res/relay/namespace/main.bicep @@ -28,17 +28,21 @@ param authorizationRules array = [ } ] +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointSingleServiceType[]? @description('Optional. Configure networking options for Relay. This object contains IPs/Subnets to allow or restrict access to private endpoints only. For security reasons, it is recommended to configure this object on the Namespace.') param networkRuleSets object = {} @@ -354,172 +358,3 @@ output privateEndpoints array = [ networkInterfaceIds: namespace_privateEndpoints[i].outputs.networkInterfaceIds } ] - -// =============== // -// Definitions // -// =============== // - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') - service: string? - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? - - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? - - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? - - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? diff --git a/avm/res/relay/namespace/main.json b/avm/res/relay/namespace/main.json index dab21e582d..9f8094485f 100644 --- a/avm/res/relay/namespace/main.json +++ b/avm/res/relay/namespace/main.json @@ -5,451 +5,491 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "10748276001217770184" + "version": "0.30.23.60470", + "templateHash": "14262477260882181529" }, "name": "Relay Namespaces", "description": "This module deploys a Relay Namespace", "owner": "Azure/module-maintainers" }, "definitions": { - "lockType": { + "_1.privateEndpointCustomDnsConfigType": { "type": "object", "properties": { - "name": { + "fqdn": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Required. A list of private IP addresses of the private endpoint." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." - } - }, - "privateDnsZoneGroup": { + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." + "description": "Optional. The name of the private DNS Zone Group config." } }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, + "privateDnsZoneResourceId": { + "type": "string", "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + "description": "Required. The resource id of the private DNS zone." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." } }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } - }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." } }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "privateEndpointSingleServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private Endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the Private Endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the Private Endpoint for. For example \"vault\" for a Key Vault Private Endpoint." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS Zone Group to configure for the Private Endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the Private Endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the Private Endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/Resource Groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like 'vault' for key vault).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -495,25 +535,38 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointSingleServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } @@ -710,8 +763,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13234316448276715063" + "version": "0.30.23.60470", + "templateHash": "9137586793857005081" }, "name": "Relay Namespace Authorization Rules", "description": "This module deploys a Relay Namespace Authorization Rule.", @@ -809,8 +862,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13158990350519912635" + "version": "0.30.23.60470", + "templateHash": "9578854855013298380" }, "name": "Relay Namespace Network Rules Sets", "description": "This module deploys a Relay Namespace Network Rule Set.", @@ -938,8 +991,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "3066452421480890151" + "version": "0.30.23.60470", + "templateHash": "16821503954722419440" }, "name": "Relay Namespace Hybrid Connections", "description": "This module deploys a Relay Namespace Hybrid Connection.", @@ -1223,8 +1276,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11780139902470137859" + "version": "0.30.23.60470", + "templateHash": "4431168643851665214" }, "name": "Hybrid Connection Authorization Rules", "description": "This module deploys a Hybrid Connection Authorization Rule.", @@ -1366,8 +1419,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "25032660008872161" + "version": "0.30.23.60470", + "templateHash": "10679723922873486376" }, "name": "Relay Namespace WCF Relays", "description": "This module deploys a Relay Namespace WCF Relay.", @@ -1671,8 +1724,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9846145731132177305" + "version": "0.30.23.60470", + "templateHash": "15492272456787428584" }, "name": "WCF Relay Authorization Rules", "description": "This module deploys a WCF Relay Authorization Rule.", diff --git a/avm/res/relay/namespace/network-rule-set/main.json b/avm/res/relay/namespace/network-rule-set/main.json index 3af1bab1b5..2ed1fecd4a 100644 --- a/avm/res/relay/namespace/network-rule-set/main.json +++ b/avm/res/relay/namespace/network-rule-set/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13158990350519912635" + "version": "0.30.23.60470", + "templateHash": "9578854855013298380" }, "name": "Relay Namespace Network Rules Sets", "description": "This module deploys a Relay Namespace Network Rule Set.", diff --git a/avm/res/relay/namespace/wcf-relay/authorization-rule/main.json b/avm/res/relay/namespace/wcf-relay/authorization-rule/main.json index a864b5d569..851d97b435 100644 --- a/avm/res/relay/namespace/wcf-relay/authorization-rule/main.json +++ b/avm/res/relay/namespace/wcf-relay/authorization-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9846145731132177305" + "version": "0.30.23.60470", + "templateHash": "15492272456787428584" }, "name": "WCF Relay Authorization Rules", "description": "This module deploys a WCF Relay Authorization Rule.", diff --git a/avm/res/relay/namespace/wcf-relay/main.json b/avm/res/relay/namespace/wcf-relay/main.json index 681b9dac73..84c4e487cb 100644 --- a/avm/res/relay/namespace/wcf-relay/main.json +++ b/avm/res/relay/namespace/wcf-relay/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "25032660008872161" + "version": "0.30.23.60470", + "templateHash": "10679723922873486376" }, "name": "Relay Namespace WCF Relays", "description": "This module deploys a Relay Namespace WCF Relay.", @@ -310,8 +310,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9846145731132177305" + "version": "0.30.23.60470", + "templateHash": "15492272456787428584" }, "name": "WCF Relay Authorization Rules", "description": "This module deploys a WCF Relay Authorization Rule.", diff --git a/avm/res/resources/deployment-script/README.md b/avm/res/resources/deployment-script/README.md index 6cb35243e4..cde40a6843 100644 --- a/avm/res/resources/deployment-script/README.md +++ b/avm/res/resources/deployment-script/README.md @@ -8,6 +8,7 @@ This module deploys Deployment Scripts. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types @@ -51,7 +52,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: kind: 'AzureCLI' name: 'rdscli001' // Non-required parameters - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' environmentVariables: [ { name: 'var1' @@ -60,7 +61,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: ] location: '' managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -92,7 +93,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, // Non-required parameters "azCliVersion": { - "value": "2.9.1" + "value": "2.52.0" }, "environmentVariables": { "value": [ @@ -107,7 +108,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, "managedIdentities": { "value": { - "userAssignedResourcesIds": [ + "userAssignedResourceIds": [ "" ] } @@ -139,7 +140,7 @@ using 'br/public:avm/res/resources/deployment-script:' param kind = 'AzureCLI' param name = 'rdscli001' // Non-required parameters -param azCliVersion = '2.9.1' +param azCliVersion = '2.52.0' param environmentVariables = [ { name: 'var1' @@ -148,7 +149,7 @@ param environmentVariables = [ ] param location = '' param managedIdentities = { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -177,10 +178,10 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: kind: 'AzurePowerShell' name: 'rdsmin001' // Non-required parameters - azPowerShellVersion: '9.7' + azPowerShellVersion: '12.3' location: '' managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -210,14 +211,14 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, // Non-required parameters "azPowerShellVersion": { - "value": "9.7" + "value": "12.3" }, "location": { "value": "" }, "managedIdentities": { "value": { - "userAssignedResourcesIds": [ + "userAssignedResourceIds": [ "" ] } @@ -243,10 +244,10 @@ using 'br/public:avm/res/resources/deployment-script:' param kind = 'AzurePowerShell' param name = 'rdsmin001' // Non-required parameters -param azPowerShellVersion = '9.7' +param azPowerShellVersion = '12.3' param location = '' param managedIdentities = { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -274,7 +275,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: name: 'rdsmax001' // Non-required parameters arguments: '-argument1 \\\'test\\\'' - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' cleanupPreference: 'Always' containerGroupName: 'dep-cg-rdsmax' environmentVariables: [ @@ -292,7 +293,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: kind: 'None' } managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -353,7 +354,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: "value": "-argument1 \\\"test\\\"" }, "azCliVersion": { - "value": "2.9.1" + "value": "2.52.0" }, "cleanupPreference": { "value": "Always" @@ -383,7 +384,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, "managedIdentities": { "value": { - "userAssignedResourcesIds": [ + "userAssignedResourceIds": [ "" ] } @@ -450,7 +451,7 @@ param kind = 'AzureCLI' param name = 'rdsmax001' // Non-required parameters param arguments = '-argument1 \\\'test\\\'' -param azCliVersion = '2.9.1' +param azCliVersion = '2.52.0' param cleanupPreference = 'Always' param containerGroupName = 'dep-cg-rdsmax' param environmentVariables = [ @@ -468,7 +469,7 @@ param lock = { kind: 'None' } param managedIdentities = { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -523,11 +524,11 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: kind: 'AzureCLI' name: 'rdspe001' // Non-required parameters - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' cleanupPreference: 'Always' location: '' managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -564,7 +565,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, // Non-required parameters "azCliVersion": { - "value": "2.9.1" + "value": "2.52.0" }, "cleanupPreference": { "value": "Always" @@ -574,7 +575,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, "managedIdentities": { "value": { - "userAssignedResourcesIds": [ + "userAssignedResourceIds": [ "" ] } @@ -617,11 +618,11 @@ using 'br/public:avm/res/resources/deployment-script:' param kind = 'AzureCLI' param name = 'rdspe001' // Non-required parameters -param azCliVersion = '2.9.1' +param azCliVersion = '2.52.0' param cleanupPreference = 'Always' param location = '' param managedIdentities = { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -655,11 +656,11 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: kind: 'AzureCLI' name: 'rdsnet001' // Non-required parameters - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' cleanupPreference: 'Always' location: '' managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -696,7 +697,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, // Non-required parameters "azCliVersion": { - "value": "2.9.1" + "value": "2.52.0" }, "cleanupPreference": { "value": "Always" @@ -706,7 +707,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, "managedIdentities": { "value": { - "userAssignedResourcesIds": [ + "userAssignedResourceIds": [ "" ] } @@ -749,11 +750,11 @@ using 'br/public:avm/res/resources/deployment-script:' param kind = 'AzureCLI' param name = 'rdsnet001' // Non-required parameters -param azCliVersion = '2.9.1' +param azCliVersion = '2.52.0' param cleanupPreference = 'Always' param location = '' param managedIdentities = { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -788,10 +789,10 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: name: 'rdsps001' // Non-required parameters arguments: '-var1 \\\'AVM Deployment Script test!\\\'' - azPowerShellVersion: '9.7' + azPowerShellVersion: '12.3' location: '' managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -826,14 +827,14 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: "value": "-var1 \\\"AVM Deployment Script test!\\\"" }, "azPowerShellVersion": { - "value": "9.7" + "value": "12.3" }, "location": { "value": "" }, "managedIdentities": { "value": { - "userAssignedResourcesIds": [ + "userAssignedResourceIds": [ "" ] } @@ -866,10 +867,10 @@ param kind = 'AzurePowerShell' param name = 'rdsps001' // Non-required parameters param arguments = '-var1 \\\'AVM Deployment Script test!\\\'' -param azPowerShellVersion = '9.7' +param azPowerShellVersion = '12.3' param location = '' param managedIdentities = { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -898,14 +899,14 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: kind: 'AzureCLI' name: 'rdswaf001' // Non-required parameters - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' cleanupPreference: 'Always' location: '' lock: { kind: 'None' } managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -944,7 +945,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, // Non-required parameters "azCliVersion": { - "value": "2.9.1" + "value": "2.52.0" }, "cleanupPreference": { "value": "Always" @@ -959,7 +960,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script: }, "managedIdentities": { "value": { - "userAssignedResourcesIds": [ + "userAssignedResourceIds": [ "" ] } @@ -1004,14 +1005,14 @@ using 'br/public:avm/res/resources/deployment-script:' param kind = 'AzureCLI' param name = 'rdswaf001' // Non-required parameters -param azCliVersion = '2.9.1' +param azCliVersion = '2.52.0' param cleanupPreference = 'Always' param location = '' param lock = { kind: 'None' } param managedIdentities = { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -1155,8 +1156,13 @@ The environment variables to pass over to the script. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-environmentvariablesname) | string | The name of the environment variable. | -| [`secureValue`](#parameter-environmentvariablessecurevalue) | securestring | The value of the secure environment variable. | -| [`value`](#parameter-environmentvariablesvalue) | string | The value of the environment variable. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`secureValue`](#parameter-environmentvariablessecurevalue) | securestring | The value of the secure environment variable. Required if `value` is null. | +| [`value`](#parameter-environmentvariablesvalue) | string | The value of the environment variable. Required if `secureValue` is null. | ### Parameter: `environmentVariables.name` @@ -1167,14 +1173,14 @@ The name of the environment variable. ### Parameter: `environmentVariables.secureValue` -The value of the secure environment variable. +The value of the secure environment variable. Required if `value` is null. - Required: No - Type: securestring ### Parameter: `environmentVariables.value` -The value of the environment variable. +The value of the environment variable. Required if `secureValue` is null. - Required: No - Type: string @@ -1234,13 +1240,13 @@ The managed identity definition for this resource. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`userAssignedResourcesIds`](#parameter-managedidentitiesuserassignedresourcesids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | -### Parameter: `managedIdentities.userAssignedResourcesIds` +### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. -- Required: Yes +- Required: No - Type: array ### Parameter: `primaryScriptUri` @@ -1431,6 +1437,14 @@ Do not provide a value! This date value is used to make sure the script run ever | `resourceGroupName` | string | The resource group the deployment script was deployed into. | | `resourceId` | string | The resource ID of the deployment script. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/resources/deployment-script/main.bicep b/avm/res/resources/deployment-script/main.bicep index 49b96d7a48..9ee3886795 100644 --- a/avm/res/resources/deployment-script/main.bicep +++ b/avm/res/resources/deployment-script/main.bicep @@ -19,8 +19,9 @@ param location string = resourceGroup().location ]) param kind string +import { managedIdentityOnlyUserAssignedType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityOnlyUserAssignedType? @description('Optional. Resource tags.') param tags object? @@ -75,11 +76,13 @@ param storageAccountResourceId 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? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true @@ -125,19 +128,19 @@ var containerSettings = { } var formattedUserAssignedIdentities = reduce( - map((managedIdentities.?userAssignedResourcesIds ?? []), (id) => { '${id}': {} }), + map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next) ) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } var identity = !empty(managedIdentities) ? { - type: !empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null + type: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null -resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' existing = if (!empty(storageAccountResourceId)) { +resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing = if (!empty(storageAccountResourceId)) { name: last(split((!empty(storageAccountResourceId) ? storageAccountResourceId : 'dummyAccount'), '/'))! scope: resourceGroup( split((!empty(storageAccountResourceId) ? storageAccountResourceId : '//'), '/')[2], @@ -256,53 +259,14 @@ output deploymentScriptLogs string[] = split(deploymentScriptLogs.properties.log // Definitions // // ================ // -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type managedIdentitiesType = { - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourcesIds: string[] -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - type environmentVariableType = { @description('Required. The name of the environment variable.') name: string - @description('Required. The value of the secure environment variable.') + @description('Conditional. The value of the secure environment variable. Required if `value` is null.') @secure() secureValue: string? - @description('Required. The value of the environment variable.') + @description('Conditional. The value of the environment variable. Required if `secureValue` is null.') value: string? } diff --git a/avm/res/resources/deployment-script/main.json b/avm/res/resources/deployment-script/main.json index 37eaaa6a2a..49a7c1bf8c 100644 --- a/avm/res/resources/deployment-script/main.json +++ b/avm/res/resources/deployment-script/main.json @@ -5,14 +5,39 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8443498654175834102" + "version": "0.30.23.60470", + "templateHash": "17881568717048891322" }, "name": "Deployment Scripts", "description": "This module deploys Deployment Scripts.", "owner": "Azure/module-maintainers" }, "definitions": { + "environmentVariableType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the environment variable." + } + }, + "secureValue": { + "type": "securestring", + "nullable": true, + "metadata": { + "description": "Conditional. The value of the secure environment variable. Required if `value` is null." + } + }, + "value": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Conditional. The value of the environment variable. Required if `secureValue` is null." + } + } + } + }, "lockType": { "type": "object", "properties": { @@ -36,118 +61,106 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "managedIdentitiesType": { + "managedIdentityOnlyUserAssignedType": { "type": "object", "properties": { - "userAssignedResourcesIds": { + "userAssignedResourceIds": { "type": "array", "items": { "type": "string" }, + "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." } } }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" } - }, - "nullable": true + } }, - "environmentVariableType": { + "roleAssignmentType": { "type": "object", "properties": { "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The name of the environment variable." + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "secureValue": { - "type": "securestring", + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], "nullable": true, "metadata": { - "description": "Required. The value of the secure environment variable." + "description": "Optional. The principal type of the assigned principal ID." } }, - "value": { + "description": { "type": "string", "nullable": true, "metadata": { - "description": "Required. The value of the environment variable." + "description": "Optional. The description of the role assignment." } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" } } } @@ -178,7 +191,8 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityOnlyUserAssignedType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } @@ -308,12 +322,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -352,15 +371,15 @@ "containerGroupName": "[parameters('containerGroupName')]", "subnetIds": "[if(not(empty(coalesce(variables('subnetIds'), createArray()))), variables('subnetIds'), null())]" }, - "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", - "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createObject()))), 'UserAssigned', null()), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]" + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null()), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]" }, "resources": { "storageAccount": { "condition": "[not(empty(parameters('storageAccountResourceId')))]", "existing": true, "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2021-04-01", + "apiVersion": "2023-05-01", "subscriptionId": "[split(if(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountResourceId'), '//'), '/')[2]]", "resourceGroup": "[split(if(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountResourceId'), '////'), '/')[4]]", "name": "[last(split(if(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountResourceId'), 'dummyAccount'), '/'))]" diff --git a/avm/res/resources/deployment-script/tests/e2e/cli/main.test.bicep b/avm/res/resources/deployment-script/tests/e2e/cli/main.test.bicep index 461b6f0409..67725082af 100644 --- a/avm/res/resources/deployment-script/tests/e2e/cli/main.test.bicep +++ b/avm/res/resources/deployment-script/tests/e2e/cli/main.test.bicep @@ -51,7 +51,7 @@ module testDeployment '../../../main.bicep' = { params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' kind: 'AzureCLI' retentionInterval: 'P1D' environmentVariables: [ @@ -63,7 +63,7 @@ module testDeployment '../../../main.bicep' = { scriptContent: 'echo \'Enviornment variable value is: \' $var1' storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } diff --git a/avm/res/resources/deployment-script/tests/e2e/defaults/main.test.bicep b/avm/res/resources/deployment-script/tests/e2e/defaults/main.test.bicep index 48cdcc9741..f6aa3d3468 100644 --- a/avm/res/resources/deployment-script/tests/e2e/defaults/main.test.bicep +++ b/avm/res/resources/deployment-script/tests/e2e/defaults/main.test.bicep @@ -50,11 +50,11 @@ module testDeployment '../../../main.bicep' = { params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - azPowerShellVersion: '9.7' + azPowerShellVersion: '12.3' kind: 'AzurePowerShell' scriptContent: 'Write-Host \'AVM Deployment Script test!\'' managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } diff --git a/avm/res/resources/deployment-script/tests/e2e/max/main.test.bicep b/avm/res/resources/deployment-script/tests/e2e/max/main.test.bicep index 5311631d44..09e967f3cc 100644 --- a/avm/res/resources/deployment-script/tests/e2e/max/main.test.bicep +++ b/avm/res/resources/deployment-script/tests/e2e/max/main.test.bicep @@ -51,7 +51,7 @@ module testDeployment '../../../main.bicep' = { params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' kind: 'AzureCLI' retentionInterval: 'P1D' cleanupPreference: 'Always' @@ -76,7 +76,7 @@ module testDeployment '../../../main.bicep' = { } ] managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } diff --git a/avm/res/resources/deployment-script/tests/e2e/private-endpoint/main.test.bicep b/avm/res/resources/deployment-script/tests/e2e/private-endpoint/main.test.bicep index 67a1eb7402..6805475cf1 100644 --- a/avm/res/resources/deployment-script/tests/e2e/private-endpoint/main.test.bicep +++ b/avm/res/resources/deployment-script/tests/e2e/private-endpoint/main.test.bicep @@ -53,7 +53,7 @@ module testDeployment '../../../main.bicep' = { params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' kind: 'AzureCLI' retentionInterval: 'P1D' cleanupPreference: 'Always' @@ -61,7 +61,7 @@ module testDeployment '../../../main.bicep' = { nestedDependencies.outputs.subnetResourceId ] managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } diff --git a/avm/res/resources/deployment-script/tests/e2e/private-network/main.test.bicep b/avm/res/resources/deployment-script/tests/e2e/private-network/main.test.bicep index a3ba9539db..1c568ec90e 100644 --- a/avm/res/resources/deployment-script/tests/e2e/private-network/main.test.bicep +++ b/avm/res/resources/deployment-script/tests/e2e/private-network/main.test.bicep @@ -52,7 +52,7 @@ module testDeployment '../../../main.bicep' = { params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' kind: 'AzureCLI' retentionInterval: 'P1D' cleanupPreference: 'Always' @@ -60,7 +60,7 @@ module testDeployment '../../../main.bicep' = { nestedDependencies.outputs.subnetResourceId ] managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } diff --git a/avm/res/resources/deployment-script/tests/e2e/ps/main.test.bicep b/avm/res/resources/deployment-script/tests/e2e/ps/main.test.bicep index 3ec26ca905..f30d89377d 100644 --- a/avm/res/resources/deployment-script/tests/e2e/ps/main.test.bicep +++ b/avm/res/resources/deployment-script/tests/e2e/ps/main.test.bicep @@ -51,14 +51,14 @@ module testDeployment '../../../main.bicep' = { params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - azPowerShellVersion: '9.7' + azPowerShellVersion: '12.3' kind: 'AzurePowerShell' retentionInterval: 'P1D' arguments: '-var1 \\"AVM Deployment Script test!\\"' scriptContent: 'param([string] $var1);Write-Host \'Argument var1 value is:\' $var1' storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } diff --git a/avm/res/resources/deployment-script/tests/e2e/waf-aligned/main.test.bicep b/avm/res/resources/deployment-script/tests/e2e/waf-aligned/main.test.bicep index 4277a59fc1..69828fe1bc 100644 --- a/avm/res/resources/deployment-script/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/resources/deployment-script/tests/e2e/waf-aligned/main.test.bicep @@ -51,7 +51,7 @@ module testDeployment '../../../main.bicep' = { params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - azCliVersion: '2.9.1' + azCliVersion: '2.52.0' kind: 'AzureCLI' retentionInterval: 'P1D' cleanupPreference: 'Always' @@ -68,7 +68,7 @@ module testDeployment '../../../main.bicep' = { scriptContent: 'echo \'AVM Deployment Script test!\'' storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId managedIdentities: { - userAssignedResourcesIds: [ + userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } diff --git a/avm/res/resources/deployment-script/version.json b/avm/res/resources/deployment-script/version.json index 13669e6601..41fc8c654f 100644 --- a/avm/res/resources/deployment-script/version.json +++ b/avm/res/resources/deployment-script/version.json @@ -1,7 +1,7 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.5", "pathFilters": [ "./main.json" ] -} \ No newline at end of file +} diff --git a/avm/res/search/search-service/README.md b/avm/res/search/search-service/README.md index 056c76fef4..22bf2edaaf 100644 --- a/avm/res/search/search-service/README.md +++ b/avm/res/search/search-service/README.md @@ -255,6 +255,7 @@ module searchService 'br/public:avm/res/search/search-service:' = { ] } networkRuleSet: { + bypass: 'AzurePortal' ipRules: [ { value: '40.74.28.0/23' @@ -364,6 +365,7 @@ module searchService 'br/public:avm/res/search/search-service:' = { }, "networkRuleSet": { "value": { + "bypass": "AzurePortal", "ipRules": [ { "value": "40.74.28.0/23" @@ -465,6 +467,7 @@ param managedIdentities = { ] } param networkRuleSet = { + bypass: 'AzurePortal' ipRules: [ { value: '40.74.28.0/23' @@ -971,7 +974,7 @@ param tags = { | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`hostingMode`](#parameter-hostingmode) | string | Applicable only for the standard3 SKU. You can set this property to enable up to 3 high density partitions that allow up to 1000 indexes, which is much higher than the maximum indexes allowed for any other SKU. For the standard3 SKU, the value is either 'default' or 'highDensity'. For all other SKUs, this value must be 'default'. | | [`location`](#parameter-location) | string | Location for all Resources. | -| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`lock`](#parameter-lock) | object | The lock settings for all Resources in the solution. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | | [`networkRuleSet`](#parameter-networkruleset) | object | Network specific rules that determine how the Azure Cognitive Search service may be reached. | | [`partitionCount`](#parameter-partitioncount) | int | The number of partitions in the search service; if specified, it can be 1, 2, 3, 4, 6, or 12. Values greater than 1 are only valid for standard SKUs. For 'standard3' services with hostingMode set to 'highDensity', the allowed values are between 1 and 3. | @@ -998,7 +1001,47 @@ Defines the options for how the data plane API of a Search service authenticates - Required: No - Type: object -- Default: `{}` + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`aadOrApiKey`](#parameter-authoptionsaadorapikey) | object | Indicates that either the API key or an access token from a Microsoft Entra ID tenant can be used for authentication. | +| [`apiKeyOnly`](#parameter-authoptionsapikeyonly) | object | Indicates that only the API key can be used for authentication. | + +### Parameter: `authOptions.aadOrApiKey` + +Indicates that either the API key or an access token from a Microsoft Entra ID tenant can be used for authentication. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`aadAuthFailureMode`](#parameter-authoptionsaadorapikeyaadauthfailuremode) | string | Describes what response the data plane API of a search service would send for requests that failed authentication. | + +### Parameter: `authOptions.aadOrApiKey.aadAuthFailureMode` + +Describes what response the data plane API of a search service would send for requests that failed authentication. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'http401WithBearerChallenge' + 'http403' + ] + ``` + +### Parameter: `authOptions.apiKeyOnly` + +Indicates that only the API key can be used for authentication. + +- Required: No +- Type: object ### Parameter: `cmkEnforcement` @@ -1033,7 +1076,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -1143,7 +1186,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -1203,7 +1246,7 @@ Location for all Resources. ### Parameter: `lock` -The lock settings of the service. +The lock settings for all Resources in the solution. - Required: No - Type: object @@ -1271,7 +1314,47 @@ Network specific rules that determine how the Azure Cognitive Search service may - Required: No - Type: object -- Default: `{}` + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`bypass`](#parameter-networkrulesetbypass) | string | Network specific rules that determine how the Azure AI Search service may be reached. | +| [`ipRules`](#parameter-networkrulesetiprules) | array | A list of IP restriction rules that defines the inbound network(s) with allowing access to the search service endpoint. At the meantime, all other public IP networks are blocked by the firewall. These restriction rules are applied only when the 'publicNetworkAccess' of the search service is 'enabled'; otherwise, traffic over public interface is not allowed even with any public IP rules, and private endpoint connections would be the exclusive access method. | + +### Parameter: `networkRuleSet.bypass` + +Network specific rules that determine how the Azure AI Search service may be reached. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzurePortal' + 'None' + ] + ``` + +### Parameter: `networkRuleSet.ipRules` + +A list of IP restriction rules that defines the inbound network(s) with allowing access to the search service endpoint. At the meantime, all other public IP networks are blocked by the firewall. These restriction rules are applied only when the 'publicNetworkAccess' of the search service is 'enabled'; otherwise, traffic over public interface is not allowed even with any public IP rules, and private endpoint connections would be the exclusive access method. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`value`](#parameter-networkrulesetiprulesvalue) | string | Value corresponding to a single IPv4 address (eg., 123.1.2.3) or an IP range in CIDR format (eg., 123.1.2.3/24) to be allowed. | + +### Parameter: `networkRuleSet.ipRules.value` + +Value corresponding to a single IPv4 address (eg., 123.1.2.3) or an IP range in CIDR format (eg., 123.1.2.3/24) to be allowed. + +- Required: Yes +- Type: string ### Parameter: `partitionCount` @@ -1298,22 +1381,22 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the Private Endpoint IP configuration is included. | | [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | -| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the Private Endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. | | [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | -| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the Private Endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | -| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS zone group to configure for the private endpoint. | +| [`name`](#parameter-privateendpointsname) | string | The name of the Private Endpoint. | +| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS Zone Group to configure for the Private Endpoint. | | [`privateLinkServiceConnectionName`](#parameter-privateendpointsprivatelinkserviceconnectionname) | string | The name of the private link connection to create. | -| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. | +| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | -| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/Resource Groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -1324,7 +1407,7 @@ Resource ID of the subnet where the endpoint needs to be created. ### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` -Application security groups in which the private endpoint IP configuration is included. +Application security groups in which the Private Endpoint IP configuration is included. - Required: No - Type: array @@ -1340,15 +1423,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1357,9 +1438,16 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` -The custom name of the network interface attached to the private endpoint. +The custom name of the network interface attached to the Private Endpoint. - Required: No - Type: string @@ -1373,7 +1461,7 @@ Enable/Disable usage telemetry for module. ### Parameter: `privateEndpoints.ipConfigurations` -A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. +A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. - Required: No - Type: array @@ -1437,7 +1525,7 @@ If Manual Private Link Connection is required. ### Parameter: `privateEndpoints.location` -The location to deploy the private endpoint to. +The location to deploy the Private Endpoint to. - Required: No - Type: string @@ -1487,14 +1575,14 @@ A message passed to the owner of the remote resource with the manual connection ### Parameter: `privateEndpoints.name` -The name of the private endpoint. +The name of the Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.privateDnsZoneGroup` -The private DNS zone group to configure for the private endpoint. +The private DNS Zone Group to configure for the Private Endpoint. - Required: No - Type: object @@ -1503,7 +1591,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -1513,7 +1601,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -1528,7 +1616,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -1539,7 +1627,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -1560,7 +1648,7 @@ The name of the private link connection to create. ### Parameter: `privateEndpoints.resourceGroupName` -Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. +Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. - Required: No - Type: string @@ -1675,14 +1763,14 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". +The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.tags` -Tags to be applied on all resources/resource groups in this deployment. +Tags to be applied on all resources/Resource Groups in this deployment. - Required: No - Type: object @@ -1925,6 +2013,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.3.0` | Remote reference | ## Data Collection diff --git a/avm/res/search/search-service/main.bicep b/avm/res/search/search-service/main.bicep index df608c8af6..b9868f4b64 100644 --- a/avm/res/search/search-service/main.bicep +++ b/avm/res/search/search-service/main.bicep @@ -10,7 +10,7 @@ metadata owner = 'Azure/module-maintainers' param name string @description('Optional. Defines the options for how the data plane API of a Search service authenticates requests. Must remain an empty object {} if \'disableLocalAuth\' is set to true.') -param authOptions object = {} +param authOptions authOptionsType? @description('Optional. When set to true, calls to the search service will not be permitted to utilize API keys for authentication. This cannot be set to true if \'authOptions\' are defined.') param disableLocalAuth bool = true @@ -36,19 +36,21 @@ param hostingMode string = 'default' @description('Optional. Location for all Resources.') param location string = resourceGroup().location -@description('Optional. The lock settings of the service.') -param lock lockType +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.3.0' +@description('Optional. The lock settings for all Resources in the solution.') +param lock lockType? @description('Optional. Network specific rules that determine how the Azure Cognitive Search service may be reached.') -param networkRuleSet object = {} +param networkRuleSet networkRuleSetType? @description('Optional. The number of partitions in the search service; if specified, it can be 1, 2, 3, 4, 6, or 12. Values greater than 1 are only valid for standard SKUs. For \'standard3\' services with hostingMode set to \'highDensity\', the allowed values are between 1 and 3.') @minValue(1) @maxValue(12) param partitionCount int = 1 +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.3.0' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointSingleServiceType[]? @description('Optional. The sharedPrivateLinkResources to create as part of the search Service.') param sharedPrivateLinkResources array = [] @@ -68,8 +70,9 @@ param secretsExportConfiguration secretsExportConfigurationType? @maxValue(12) param replicaCount int = 3 +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.3.0' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @allowed([ 'disabled' @@ -91,11 +94,13 @@ param semanticSearch string? ]) param sku string = 'standard' +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.3.0' @description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityAllType? +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.3.0' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? @description('Optional. Tags to help categorize the resource in the Azure portal.') param tags object? @@ -187,7 +192,7 @@ resource searchService 'Microsoft.Search/searchServices@2024-03-01-preview' = { tags: tags identity: identity properties: { - authOptions: !empty(authOptions) ? authOptions : null + authOptions: authOptions disableLocalAuth: disableLocalAuth encryptionWithCmk: { enforcement: cmkEnforcement @@ -385,179 +390,6 @@ output exportedSecrets secretsOutputType = (secretsExportConfiguration != null) // Definitions // // =============== // -type managedIdentitiesType = { - @description('Optional. Enables system assigned managed identity on the resource.') - systemAssigned: bool? - - @description('Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption.') - userAssignedResourceIds: string[]? -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') - service: string? - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? - - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? - - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? - - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? - type secretsExportConfigurationType = { @description('Required. The key vault name where to store the API Admin keys generated by the modules.') keyVaultResourceId: string @@ -574,3 +406,28 @@ type secretsOutputType = { @description('An exported secret\'s references.') *: secretSetType } + +@export() +type authOptionsType = { + @description('Optional. Indicates that either the API key or an access token from a Microsoft Entra ID tenant can be used for authentication.') + aadOrApiKey: { + @description('Optional. Describes what response the data plane API of a search service would send for requests that failed authentication.') + aadAuthFailureMode: ('http401WithBearerChallenge' | 'http403')? + }? + @description('Optional. Indicates that only the API key can be used for authentication.') + apiKeyOnly: object? +} + +@export() +type networkRuleSetType = { + @description('Optional. Network specific rules that determine how the Azure AI Search service may be reached.') + bypass: ('AzurePortal' | 'None')? + @description('Optional. A list of IP restriction rules that defines the inbound network(s) with allowing access to the search service endpoint. At the meantime, all other public IP networks are blocked by the firewall. These restriction rules are applied only when the \'publicNetworkAccess\' of the search service is \'enabled\'; otherwise, traffic over public interface is not allowed even with any public IP rules, and private endpoint connections would be the exclusive access method.') + ipRules: ipRuleType[]? +} + +@export() +type ipRuleType = { + @description('Required. Value corresponding to a single IPv4 address (eg., 123.1.2.3) or an IP range in CIDR format (eg., 123.1.2.3/24) to be allowed.') + value: string +} diff --git a/avm/res/search/search-service/main.json b/avm/res/search/search-service/main.json index 24719a5ca7..d2fd601fa8 100644 --- a/avm/res/search/search-service/main.json +++ b/avm/res/search/search-service/main.json @@ -5,507 +5,630 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13527260085574333800" + "version": "0.31.34.60546", + "templateHash": "18312735267946671495" }, "name": "Search Services", "description": "This module deploys a Search Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { + "secretsExportConfigurationType": { "type": "object", "properties": { - "systemAssigned": { - "type": "bool", + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The key vault name where to store the API Admin keys generated by the modules." + } + }, + "primaryAdminKeyName": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." + "description": "Optional. The primaryAdminKey secret name to create." } }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, + "secondaryAdminKeyName": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + "description": "Optional. The secondaryAdminKey secret name to create." } } - }, - "nullable": true + } }, - "lockType": { + "secretsOutputType": { + "type": "object", + "properties": {}, + "additionalProperties": { + "$ref": "#/definitions/secretSetType", + "metadata": { + "description": "An exported secret's references." + } + } + }, + "authOptionsType": { "type": "object", "properties": { - "name": { - "type": "string", + "aadOrApiKey": { + "type": "object", + "properties": { + "aadAuthFailureMode": { + "type": "string", + "allowedValues": [ + "http401WithBearerChallenge", + "http403" + ], + "nullable": true, + "metadata": { + "description": "Optional. Describes what response the data plane API of a search service would send for requests that failed authentication." + } + } + }, "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. Indicates that either the API key or an access token from a Microsoft Entra ID tenant can be used for authentication." } }, - "kind": { + "apiKeyOnly": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Indicates that only the API key can be used for authentication." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "networkRuleSetType": { + "type": "object", + "properties": { + "bypass": { "type": "string", "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" + "AzurePortal", + "None" ], "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Optional. Network specific rules that determine how the Azure AI Search service may be reached." + } + }, + "ipRules": { + "type": "array", + "items": { + "$ref": "#/definitions/ipRuleType" + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP restriction rules that defines the inbound network(s) with allowing access to the search service endpoint. At the meantime, all other public IP networks are blocked by the firewall. These restriction rules are applied only when the 'publicNetworkAccess' of the search service is 'enabled'; otherwise, traffic over public interface is not allowed even with any public IP rules, and private endpoint connections would be the exclusive access method." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } + "ipRuleType": { + "type": "object", + "properties": { + "value": { + "type": "string", + "metadata": { + "description": "Required. Value corresponding to a single IPv4 address (eg., 123.1.2.3) or an IP range in CIDR format (eg., 123.1.2.3/24) to be allowed." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "_1.privateEndpointCustomDnsConfigType": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "privateDnsZoneGroup": { + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } + }, + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." + "description": "Optional. The name of the private DNS Zone Group config." } }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, + "privateDnsZoneResourceId": { + "type": "string", "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + "description": "Required. The resource id of the private DNS zone." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." } }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." } }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "tags": { + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } - }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } } }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } + }, + "privateEndpointSingleServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private Endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the Private Endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the Private Endpoint for. For example \"vault\" for a Key Vault Private Endpoint." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS Zone Group to configure for the Private Endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the Private Endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the Private Endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/Resource Groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like 'vault' for key vault).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } }, - "secretsExportConfigurationType": { + "roleAssignmentType": { "type": "object", "properties": { - "keyVaultResourceId": { + "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The key vault name where to store the API Admin keys generated by the modules." + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "primaryAdminKeyName": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], "nullable": true, "metadata": { - "description": "Optional. The primaryAdminKey secret name to create." + "description": "Optional. The principal type of the assigned principal ID." } }, - "secondaryAdminKeyName": { + "description": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The secondaryAdminKey secret name to create." + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } - } - }, - "secretsOutputType": { - "type": "object", - "properties": {}, - "additionalProperties": { - "$ref": "#/definitions/secretSetType", - "metadata": { - "description": "An exported secret's references." + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" } } }, @@ -540,8 +663,8 @@ } }, "authOptions": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/authOptionsType", + "nullable": true, "metadata": { "description": "Optional. Defines the options for how the data plane API of a Search service authenticates requests. Must remain an empty object {} if 'disableLocalAuth' is set to true." } @@ -592,13 +715,14 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { - "description": "Optional. The lock settings of the service." + "description": "Optional. The lock settings for all Resources in the solution." } }, "networkRuleSet": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/networkRuleSetType", + "nullable": true, "metadata": { "description": "Optional. Network specific rules that determine how the Azure Cognitive Search service may be reached." } @@ -613,7 +737,11 @@ } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointSingleServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } @@ -653,7 +781,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -687,13 +819,18 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -759,7 +896,7 @@ "tags": "[parameters('tags')]", "identity": "[variables('identity')]", "properties": { - "authOptions": "[if(not(empty(parameters('authOptions'))), parameters('authOptions'), null())]", + "authOptions": "[parameters('authOptions')]", "disableLocalAuth": "[parameters('disableLocalAuth')]", "encryptionWithCmk": { "enforcement": "[parameters('cmkEnforcement')]" @@ -1657,8 +1794,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "1073269867332822875" + "version": "0.31.34.60546", + "templateHash": "13697564567147510981" }, "name": "Search Services Private Link Resources", "description": "This module deploys a Search Service Private Link Resource.", @@ -1719,10 +1856,7 @@ "groupId": "[parameters('groupId')]", "requestMessage": "[parameters('requestMessage')]", "resourceRegion": "[parameters('resourceRegion')]" - }, - "dependsOn": [ - "searchService" - ] + } } }, "outputs": { @@ -1781,8 +1915,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "12263717469683062316" + "version": "0.31.34.60546", + "templateHash": "251825345610643647" } }, "definitions": { @@ -1858,10 +1992,7 @@ "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('secretsToSet')[copyIndex()].name)]", "properties": { "value": "[parameters('secretsToSet')[copyIndex()].value]" - }, - "dependsOn": [ - "keyVault" - ] + } } }, "outputs": { diff --git a/avm/res/search/search-service/shared-private-link-resource/main.json b/avm/res/search/search-service/shared-private-link-resource/main.json index ccb69cdd79..e465debc7b 100644 --- a/avm/res/search/search-service/shared-private-link-resource/main.json +++ b/avm/res/search/search-service/shared-private-link-resource/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2330033720810948871" + "version": "0.31.34.60546", + "templateHash": "13697564567147510981" }, "name": "Search Services Private Link Resources", "description": "This module deploys a Search Service Private Link Resource.", @@ -67,10 +67,7 @@ "groupId": "[parameters('groupId')]", "requestMessage": "[parameters('requestMessage')]", "resourceRegion": "[parameters('resourceRegion')]" - }, - "dependsOn": [ - "searchService" - ] + } } }, "outputs": { diff --git a/avm/res/search/search-service/tests/e2e/max/main.test.bicep b/avm/res/search/search-service/tests/e2e/max/main.test.bicep index 0fc341ea23..93c3460fa4 100644 --- a/avm/res/search/search-service/tests/e2e/max/main.test.bicep +++ b/avm/res/search/search-service/tests/e2e/max/main.test.bicep @@ -111,6 +111,7 @@ module testDeployment '../../../main.bicep' = [ } ] networkRuleSet: { + bypass: 'AzurePortal' ipRules: [ { value: '40.74.28.0/23' diff --git a/avm/res/search/search-service/version.json b/avm/res/search/search-service/version.json index 7e1d3f4157..9a9a06e897 100644 --- a/avm/res/search/search-service/version.json +++ b/avm/res/search/search-service/version.json @@ -1,7 +1,7 @@ { - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.7", - "pathFilters": [ - "./main.json" - ] + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.8", + "pathFilters": [ + "./main.json" + ] } \ No newline at end of file diff --git a/avm/res/service-bus/namespace/README.md b/avm/res/service-bus/namespace/README.md index bce7d6853c..94af8bd1dd 100644 --- a/avm/res/service-bus/namespace/README.md +++ b/avm/res/service-bus/namespace/README.md @@ -146,7 +146,7 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { location: '' managedIdentities: { systemAssigned: false - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -188,7 +188,7 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { "managedIdentities": { "value": { "systemAssigned": false, - "userAssignedResourcesIds": [ + "userAssignedResourceIds": [ "" ] } @@ -224,7 +224,7 @@ param customerManagedKey = { param location = '' param managedIdentities = { systemAssigned: false - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -297,7 +297,7 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { } managedIdentities: { systemAssigned: true - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -560,7 +560,7 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { "managedIdentities": { "value": { "systemAssigned": true, - "userAssignedResourcesIds": [ + "userAssignedResourceIds": [ "" ] } @@ -829,7 +829,7 @@ param lock = { } param managedIdentities = { systemAssigned: true - userAssignedResourcesIds: [ + userAssignedResourceIds: [ '' ] } @@ -1062,19 +1062,7 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { workspaceResourceId: '' } ] - disableLocalAuth: true location: '' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - managedIdentities: { - systemAssigned: true - userAssignedResourcesIds: [ - '' - ] - } - minimumTlsVersion: '1.2' networkRuleSets: { defaultAction: 'Deny' ipRules: [ @@ -1095,7 +1083,6 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { } ] } - premiumMessagingPartitions: 1 privateEndpoints: [ { privateDnsZoneGroup: { @@ -1140,11 +1127,6 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { roleAssignments: [] } ] - roleAssignments: [] - skuObject: { - capacity: 2 - name: 'Premium' - } tags: { Environment: 'Non-Prod' 'hidden-title': 'This is visible in the resource name' @@ -1223,29 +1205,9 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { } ] }, - "disableLocalAuth": { - "value": true - }, "location": { "value": "" }, - "lock": { - "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" - } - }, - "managedIdentities": { - "value": { - "systemAssigned": true, - "userAssignedResourcesIds": [ - "" - ] - } - }, - "minimumTlsVersion": { - "value": "1.2" - }, "networkRuleSets": { "value": { "defaultAction": "Deny", @@ -1268,9 +1230,6 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { ] } }, - "premiumMessagingPartitions": { - "value": 1 - }, "privateEndpoints": { "value": [ { @@ -1321,15 +1280,6 @@ module namespace 'br/public:avm/res/service-bus/namespace:' = { } ] }, - "roleAssignments": { - "value": [] - }, - "skuObject": { - "value": { - "capacity": 2, - "name": "Premium" - } - }, "tags": { "value": { "Environment": "Non-Prod", @@ -1404,19 +1354,7 @@ param diagnosticSettings = [ workspaceResourceId: '' } ] -param disableLocalAuth = true param location = '' -param lock = { - kind: 'CanNotDelete' - name: 'myCustomLockName' -} -param managedIdentities = { - systemAssigned: true - userAssignedResourcesIds: [ - '' - ] -} -param minimumTlsVersion = '1.2' param networkRuleSets = { defaultAction: 'Deny' ipRules: [ @@ -1437,7 +1375,6 @@ param networkRuleSets = { } ] } -param premiumMessagingPartitions = 1 param privateEndpoints = [ { privateDnsZoneGroup: { @@ -1482,11 +1419,6 @@ param queues = [ roleAssignments: [] } ] -param roleAssignments = [] -param skuObject = { - capacity: 2 - name: 'Premium' -} param tags = { Environment: 'Non-Prod' 'hidden-title': 'This is visible in the resource name' @@ -1527,7 +1459,6 @@ param topics = [ | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | Name of the Service Bus Namespace. | -| [`skuObject`](#parameter-skuobject) | object | The SKU of the Service Bus Namespace. Defaulted to Premium for ZoneRedundant configurations by default. | **Optional parameters** @@ -1552,6 +1483,7 @@ param topics = [ | [`queues`](#parameter-queues) | array | The queues to create in the service bus namespace. | | [`requireInfrastructureEncryption`](#parameter-requireinfrastructureencryption) | bool | Enable infrastructure encryption (double encryption). Note, this setting requires the configuration of Customer-Managed-Keys (CMK) via the corresponding module parameters. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`skuObject`](#parameter-skuobject) | object | The SKU of the Service Bus Namespace. Defaulted to Premium for ZoneRedundant configurations by default. | | [`tags`](#parameter-tags) | object | Tags of the resource. | | [`topics`](#parameter-topics) | array | The topics to create in the service bus namespace. | | [`zoneRedundant`](#parameter-zoneredundant) | bool | Enabled by default in order to align with resiliency best practices, thus requires Premium SKU. | @@ -1563,54 +1495,6 @@ Name of the Service Bus Namespace. - Required: Yes - Type: string -### Parameter: `skuObject` - -The SKU of the Service Bus Namespace. Defaulted to Premium for ZoneRedundant configurations by default. - -- Required: No -- Type: object -- Default: - ```Bicep - { - capacity: 2 - name: 'Premium' - } - ``` - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`name`](#parameter-skuobjectname) | string | Name of this SKU. - Basic, Standard, Premium. | - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`capacity`](#parameter-skuobjectcapacity) | int | The specified messaging units for the tier. Only used for Premium Sku tier. | - -### Parameter: `skuObject.name` - -Name of this SKU. - Basic, Standard, Premium. - -- Required: Yes -- Type: string -- Allowed: - ```Bicep - [ - 'Basic' - 'Premium' - 'Standard' - ] - ``` - -### Parameter: `skuObject.capacity` - -The specified messaging units for the tier. Only used for Premium Sku tier. - -- Required: No -- Type: int - ### Parameter: `alternateName` Alternate name for namespace. @@ -1738,7 +1622,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -1848,7 +1732,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -1975,7 +1859,7 @@ The managed identity definition for this resource. | Parameter | Type | Description | | :-- | :-- | :-- | | [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | -| [`userAssignedResourcesIds`](#parameter-managedidentitiesuserassignedresourcesids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | ### Parameter: `managedIdentities.systemAssigned` @@ -1984,9 +1868,9 @@ Enables system assigned managed identity on the resource. - Required: No - Type: bool -### Parameter: `managedIdentities.userAssignedResourcesIds` +### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. - Required: No - Type: array @@ -2175,22 +2059,22 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the Private Endpoint IP configuration is included. | | [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | -| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the Private Endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. | | [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | -| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the Private Endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | -| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS zone group to configure for the private endpoint. | +| [`name`](#parameter-privateendpointsname) | string | The name of the Private Endpoint. | +| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS Zone Group to configure for the Private Endpoint. | | [`privateLinkServiceConnectionName`](#parameter-privateendpointsprivatelinkserviceconnectionname) | string | The name of the private link connection to create. | -| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. | +| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | -| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/Resource Groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -2201,7 +2085,7 @@ Resource ID of the subnet where the endpoint needs to be created. ### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` -Application security groups in which the private endpoint IP configuration is included. +Application security groups in which the Private Endpoint IP configuration is included. - Required: No - Type: array @@ -2217,15 +2101,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -2234,9 +2116,16 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` -The custom name of the network interface attached to the private endpoint. +The custom name of the network interface attached to the Private Endpoint. - Required: No - Type: string @@ -2250,7 +2139,7 @@ Enable/Disable usage telemetry for module. ### Parameter: `privateEndpoints.ipConfigurations` -A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. +A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. - Required: No - Type: array @@ -2314,7 +2203,7 @@ If Manual Private Link Connection is required. ### Parameter: `privateEndpoints.location` -The location to deploy the private endpoint to. +The location to deploy the Private Endpoint to. - Required: No - Type: string @@ -2364,14 +2253,14 @@ A message passed to the owner of the remote resource with the manual connection ### Parameter: `privateEndpoints.name` -The name of the private endpoint. +The name of the Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.privateDnsZoneGroup` -The private DNS zone group to configure for the private endpoint. +The private DNS Zone Group to configure for the Private Endpoint. - Required: No - Type: object @@ -2380,7 +2269,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -2390,7 +2279,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -2405,7 +2294,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -2416,7 +2305,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -2437,7 +2326,7 @@ The name of the private link connection to create. ### Parameter: `privateEndpoints.resourceGroupName` -Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. +Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. - Required: No - Type: string @@ -2552,14 +2441,14 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". +The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.tags` -Tags to be applied on all resources/resource groups in this deployment. +Tags to be applied on all resources/Resource Groups in this deployment. - Required: No - Type: object @@ -3048,6 +2937,54 @@ The principal type of the assigned principal ID. ] ``` +### Parameter: `skuObject` + +The SKU of the Service Bus Namespace. Defaulted to Premium for ZoneRedundant configurations by default. + +- Required: No +- Type: object +- Default: + ```Bicep + { + capacity: 2 + name: 'Premium' + } + ``` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-skuobjectname) | string | Name of this SKU. - Basic, Standard, Premium. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacity`](#parameter-skuobjectcapacity) | int | The specified messaging units for the tier. Only used for Premium Sku tier. | + +### Parameter: `skuObject.name` + +Name of this SKU. - Basic, Standard, Premium. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Basic' + 'Premium' + 'Standard' + ] + ``` + +### Parameter: `skuObject.capacity` + +The specified messaging units for the tier. Only used for Premium Sku tier. + +- Required: No +- Type: int + ### Parameter: `tags` Tags of the resource. @@ -3580,6 +3517,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/service-bus/namespace/authorization-rule/main.json b/avm/res/service-bus/namespace/authorization-rule/main.json index e78d5a84b0..69891f3a56 100644 --- a/avm/res/service-bus/namespace/authorization-rule/main.json +++ b/avm/res/service-bus/namespace/authorization-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "16659347344675880024" + "version": "0.30.23.60470", + "templateHash": "4728331591356881277" }, "name": "Service Bus Namespace Authorization Rules", "description": "This module deploys a Service Bus Namespace Authorization Rule.", diff --git a/avm/res/service-bus/namespace/disaster-recovery-config/main.json b/avm/res/service-bus/namespace/disaster-recovery-config/main.json index 93ecd9ffa9..f1d4df322e 100644 --- a/avm/res/service-bus/namespace/disaster-recovery-config/main.json +++ b/avm/res/service-bus/namespace/disaster-recovery-config/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2437567647402328568" + "version": "0.30.23.60470", + "templateHash": "1218226237647695558" }, "name": "Service Bus Namespace Disaster Recovery Configs", "description": "This module deploys a Service Bus Namespace Disaster Recovery Config", diff --git a/avm/res/service-bus/namespace/main.bicep b/avm/res/service-bus/namespace/main.bicep index 7b00c06d4c..82e1fe0142 100644 --- a/avm/res/service-bus/namespace/main.bicep +++ b/avm/res/service-bus/namespace/main.bicep @@ -9,7 +9,7 @@ param name string @description('Optional. Location for all resources.') param location string = resourceGroup().location -@description('Required. The SKU of the Service Bus Namespace. Defaulted to Premium for ZoneRedundant configurations by default.') +@description('Optional. The SKU of the Service Bus Namespace. Defaulted to Premium for ZoneRedundant configurations by default.') param skuObject skuType = { name: 'Premium' capacity: 2 @@ -33,7 +33,7 @@ param alternateName string? param premiumMessagingPartitions int = 1 @description('Optional. Authorization Rules for the Service Bus namespace.') -param authorizationRules authorizationRuleType = [ +param authorizationRules authorizationRuleType[] = [ { name: 'RootManageSharedAccessKey' rights: [ @@ -45,22 +45,26 @@ param authorizationRules authorizationRuleType = [ ] @description('Optional. The migration configuration.') -param migrationConfiguration migrationConfigurationsType +param migrationConfiguration migrationConfigurationsType? @description('Optional. The disaster recovery configuration.') -param disasterRecoveryConfig disasterRecoveryConfigType +param disasterRecoveryConfig disasterRecoveryConfigType? +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityAllType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set.') @allowed([ @@ -71,8 +75,9 @@ param roleAssignments roleAssignmentType ]) param publicNetworkAccess string = '' +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointSingleServiceType[]? @description('Optional. Configure networking options for Premium SKU Service Bus. This object contains IPs/Subnets to allow or restrict access to private endpoints only. For security reasons, it is recommended to configure this object on the Namespace.') param networkRuleSets networkRuleSetType? @@ -87,19 +92,20 @@ param tags object? param enableTelemetry bool = true @description('Optional. The queues to create in the service bus namespace.') -param queues queueType? +param queues queueType[]? @description('Optional. The topics to create in the service bus namespace.') -param topics topicType? +param topics topicType[]? +import { customerManagedKeyType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The customer managed key definition.') -param customerManagedKey customerManagedKeyType +param customerManagedKey customerManagedKeyType? @description('Optional. Enable infrastructure encryption (double encryption). Note, this setting requires the configuration of Customer-Managed-Keys (CMK) via the corresponding module parameters.') param requireInfrastructureEncryption bool = true var formattedUserAssignedIdentities = reduce( - map((managedIdentities.?userAssignedResourcesIds ?? []), (id) => { '${id}': {} }), + map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next) ) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } @@ -107,8 +113,8 @@ var formattedUserAssignedIdentities = reduce( var identity = !empty(managedIdentities) ? { type: (managedIdentities.?systemAssigned ?? false) - ? (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') - : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) + ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned, UserAssigned' : 'SystemAssigned') + : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null @@ -470,193 +476,7 @@ output privateEndpoints array = [ // Definitions // // =============== // -type managedIdentitiesType = { - @description('Optional. Enables system assigned managed identity on the resource.') - systemAssigned: bool? - - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourcesIds: string[]? -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') - service: string? - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? - - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? - - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? - - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? - -type customerManagedKeyType = { - @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') - keyVaultResourceId: string - - @description('Required. The name of the customer managed key to use for encryption.') - keyName: string - - @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') - keyVersion: string? - - @description('Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use.') - userAssignedIdentityResourceId: string? -}? - +@export() type skuType = { @description('Required. Name of this SKU. - Basic, Standard, Premium.') name: ('Basic' | 'Standard' | 'Premium') @@ -665,14 +485,16 @@ type skuType = { capacity: int? } +@export() type authorizationRuleType = { @description('Required. The name of the authorization rule.') name: string @description('Optional. The rights associated with the rule.') rights: ('Listen' | 'Manage' | 'Send')[]? -}[] +} +@export() type disasterRecoveryConfigType = { @description('Optional. The name of the disaster recovery config.') name: string? @@ -682,16 +504,18 @@ type disasterRecoveryConfigType = { @description('Optional. Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing.') partnerNamespace: string? -}? +} +@export() type migrationConfigurationsType = { @description('Required. Name to access Standard Namespace after migration.') postMigrationName: string @description('Required. Existing premium Namespace resource ID which has no entities, will be used for migration.') targetNamespace: string -}? +} +@export() type networkRuleSetType = { @description('Optional. This determines if traffic is allowed over public network. Default is "Enabled". If set to "Disabled", traffic to this namespace will be restricted over Private Endpoints only and network rules will not be applied.') publicNetworkAccess: ('Disabled' | 'Enabled')? @@ -719,8 +543,9 @@ type networkRuleSetType = { @description('Required. The ID of the subnet.') subnetResourceId: string }[]? -}? +} +@export() type queueType = { @description('Required. The name of the queue.') name: string @@ -738,7 +563,7 @@ type queueType = { maxMessageSizeInKilobytes: int? @description('Optional. Authorization Rules for the Service Bus Queue.') - authorizationRules: authorizationRuleType? + authorizationRules: authorizationRuleType[]? @description('Optional. A value that indicates whether this queue has dead letter support when a message expires.') deadLetteringOnMessageExpiration: bool? @@ -777,7 +602,7 @@ type queueType = { requiresSession: bool? @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType? + roleAssignments: roleAssignmentType[]? @description('Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown.') status: ( @@ -790,14 +615,16 @@ type queueType = { | 'Deleting' | 'Renaming' | 'Unknown')? -}[]? +} +import { subscriptionType } from 'topic/main.bicep' +@export() type topicType = { @description('Required. The name of the topic.') name: string @description('Optional. Authorization Rules for the Service Bus Topic.') - authorizationRules: authorizationRuleType? + authorizationRules: authorizationRuleType[]? @description('Optional. ISO 8601 timespan idle interval after which the topic is automatically deleted. The minimum duration is 5 minutes.') autoDeleteOnIdle: string? @@ -830,7 +657,7 @@ type topicType = { requiresDuplicateDetection: bool? @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType? + roleAssignments: roleAssignmentType[]? @description('Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown.') status: ( @@ -848,68 +675,5 @@ type topicType = { supportOrdering: bool? @description('Optional. The subscriptions of the topic.') - subscriptions: { - @description('Required. The name of the service bus namespace topic subscription.') - name: string - - @description('Optional. ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes.') - autoDeleteOnIdle: string? - - @description('Optional. The properties that are associated with a subscription that is client-affine.') - clientAffineProperties: { - @description('Required. Indicates the Client ID of the application that created the client-affine subscription.') - clientId: string - - @description('Optional. For client-affine subscriptions, this value indicates whether the subscription is durable or not.') - isDurable: bool? - - @description('Optional. For client-affine subscriptions, this value indicates whether the subscription is shared or not.') - isShared: bool? - }? - - @description('Optional. A value that indicates whether a subscription has dead letter support when a message expires.') - deadLetteringOnMessageExpiration: bool? - - @description('Optional. A value that indicates whether a subscription has dead letter support when a message expires.') - deadLetteringOnFilterEvaluationExceptions: bool? - - @description('Optional. ISO 8601 timespan idle interval after which the message expires. The minimum duration is 5 minutes.') - defaultMessageTimeToLive: string? - - @description('Optional. ISO 8601 timespan that defines the duration of the duplicate detection history. The default value is 10 minutes.') - duplicateDetectionHistoryTimeWindow: string? - - @description('Optional. A value that indicates whether server-side batched operations are enabled.') - enableBatchedOperations: bool? - - @description('Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to.') - forwardDeadLetteredMessagesTo: string? - - @description('Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to.') - forwardTo: string? - - @description('Optional. A value that indicates whether the subscription supports the concept of session.') - isClientAffine: bool? - - @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.') - lockDuration: string? - - @description('Optional. Number of maximum deliveries. A message is automatically deadlettered after this number of deliveries. Default value is 10.') - maxDeliveryCount: int? - - @description('Optional. A value that indicates whether the subscription supports the concept of session.') - requiresSession: bool? - - @description('Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown.') - status: ( - | 'Active' - | 'Disabled' - | 'Restoring' - | 'SendDisabled' - | 'ReceiveDisabled' - | 'Creating' - | 'Deleting' - | 'Renaming' - | 'Unknown')? - }[]? -}[]? + subscriptions: subscriptionType[]? +} diff --git a/avm/res/service-bus/namespace/main.json b/avm/res/service-bus/namespace/main.json index 8b30c416be..7756c85f32 100644 --- a/avm/res/service-bus/namespace/main.json +++ b/avm/res/service-bus/namespace/main.json @@ -5,1119 +5,1196 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6397771352503979306" + "version": "0.30.23.60470", + "templateHash": "14946125696301743393" }, "name": "Service Bus Namespaces", "description": "This module deploys a Service Bus Namespace.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { + "skuType": { "type": "object", "properties": { - "systemAssigned": { - "type": "bool", + "name": { + "type": "string", + "allowedValues": [ + "Basic", + "Premium", + "Standard" + ], + "metadata": { + "description": "Required. Name of this SKU. - Basic, Standard, Premium." + } + }, + "capacity": { + "type": "int", "nullable": true, "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." + "description": "Optional. The specified messaging units for the tier. Only used for Premium Sku tier." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "authorizationRuleType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the authorization rule." } }, - "userAssignedResourcesIds": { + "rights": { "type": "array", - "items": { - "type": "string" - }, + "allowedValues": [ + "Listen", + "Manage", + "Send" + ], "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. The rights associated with the rule." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "lockType": { + "disasterRecoveryConfigType": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. The name of the disaster recovery config." } }, - "kind": { + "alternateName": { "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Optional. Primary/Secondary eventhub namespace name, which is part of GEO DR pairing." + } + }, + "partnerNamespace": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "migrationConfigurationsType": { + "type": "object", + "properties": { + "postMigrationName": { + "type": "string", + "metadata": { + "description": "Required. Name to access Standard Namespace after migration." + } + }, + "targetNamespace": { + "type": "string", + "metadata": { + "description": "Required. Existing premium Namespace resource ID which has no entities, will be used for migration." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." - } - }, - "privateDnsZoneGroup": { + "networkRuleSetType": { + "type": "object", + "properties": { + "publicNetworkAccess": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. This determines if traffic is allowed over public network. Default is \"Enabled\". If set to \"Disabled\", traffic to this namespace will be restricted over Private Endpoints only and network rules will not be applied." + } + }, + "defaultAction": { + "type": "string", + "allowedValues": [ + "Allow", + "Deny" + ], + "nullable": true, + "metadata": { + "description": "Optional. Default Action for Network Rule Set. Default is \"Allow\". It will not be set if publicNetworkAccess is \"Disabled\". Otherwise, it will be set to \"Deny\" if ipRules or virtualNetworkRules are being used." + } + }, + "trustedServiceAccessEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Value that indicates whether Trusted Service Access is enabled or not. Default is \"true\". It will not be set if publicNetworkAccess is \"Disabled\"." + } + }, + "ipRules": { + "type": "array", + "items": { "type": "object", "properties": { - "name": { + "action": { "type": "string", - "nullable": true, + "allowedValues": [ + "Allow", + "Deny" + ], "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." + "description": "Required. The IP filter action." } }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, + "ipMask": { + "type": "string", "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + "description": "Required. The IP mask." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." } }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } + "nullable": true, + "metadata": { + "description": "Optional. List of IpRules. It will not be set if publicNetworkAccess is \"Disabled\". Otherwise, when used, defaultAction will be set to \"Deny\"." + } + }, + "virtualNetworkRules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ignoreMissingVnetServiceEndpoint": { + "type": "bool", + "metadata": { + "description": "Required. The virtual network rule name." } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. The ID of the subnet." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." } }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } - }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } - } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. List virtual network rules. It will not be set if publicNetworkAccess is \"Disabled\". Otherwise, when used, defaultAction will be set to \"Deny\"." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "customerManagedKeyType": { + "queueType": { "type": "object", "properties": { - "keyVaultResourceId": { + "name": { "type": "string", "metadata": { - "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + "description": "Required. The name of the queue." } }, - "keyName": { + "autoDeleteOnIdle": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The name of the customer managed key to use for encryption." + "description": "Optional. ISO 8061 timeSpan idle interval after which the queue is automatically deleted. The minimum duration is 5 minutes (PT5M)." } }, - "keyVersion": { + "forwardDeadLetteredMessagesTo": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + "description": "Optional. Queue/Topic name to forward the Dead Letter message." } }, - "userAssignedIdentityResourceId": { + "forwardTo": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." - } - } - }, - "nullable": true - }, - "skuType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "allowedValues": [ - "Basic", - "Premium", - "Standard" - ], - "metadata": { - "description": "Required. Name of this SKU. - Basic, Standard, Premium." + "description": "Optional. Queue/Topic name to forward the messages." } }, - "capacity": { + "maxMessageSizeInKilobytes": { "type": "int", "nullable": true, "metadata": { - "description": "Optional. The specified messaging units for the tier. Only used for Premium Sku tier." + "description": "Optional. Maximum size (in KB) of the message payload that can be accepted by the queue. This property is only used in Premium today and default is 1024." } - } - } - }, - "authorizationRuleType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the authorization rule." - } + }, + "authorizationRules": { + "type": "array", + "items": { + "$ref": "#/definitions/authorizationRuleType" }, - "rights": { - "type": "array", - "allowedValues": [ - "Listen", - "Manage", - "Send" - ], - "nullable": true, - "metadata": { - "description": "Optional. The rights associated with the rule." - } + "nullable": true, + "metadata": { + "description": "Optional. Authorization Rules for the Service Bus Queue." } - } - } - }, - "disasterRecoveryConfigType": { - "type": "object", - "properties": { - "name": { - "type": "string", + }, + "deadLetteringOnMessageExpiration": { + "type": "bool", "nullable": true, "metadata": { - "description": "Optional. The name of the disaster recovery config." + "description": "Optional. A value that indicates whether this queue has dead letter support when a message expires." } }, - "alternateName": { + "defaultMessageTimeToLive": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Primary/Secondary eventhub namespace name, which is part of GEO DR pairing." + "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." } }, - "partnerNamespace": { + "duplicateDetectionHistoryTimeWindow": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing." + "description": "Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes." } - } - }, - "nullable": true - }, - "migrationConfigurationsType": { - "type": "object", - "properties": { - "postMigrationName": { - "type": "string", + }, + "enableBatchedOperations": { + "type": "bool", + "nullable": true, "metadata": { - "description": "Required. Name to access Standard Namespace after migration." + "description": "Optional. Value that indicates whether server-side batched operations are enabled." } }, - "targetNamespace": { - "type": "string", + "enableExpress": { + "type": "bool", + "nullable": true, "metadata": { - "description": "Required. Existing premium Namespace resource ID which has no entities, will be used for migration." + "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. This property is only used if the `service-bus/namespace` sku is Premium." } - } - }, - "nullable": true - }, - "networkRuleSetType": { - "type": "object", - "properties": { - "publicNetworkAccess": { - "type": "string", - "allowedValues": [ - "Disabled", - "Enabled" - ], + }, + "enablePartitioning": { + "type": "bool", "nullable": true, "metadata": { - "description": "Optional. This determines if traffic is allowed over public network. Default is \"Enabled\". If set to \"Disabled\", traffic to this namespace will be restricted over Private Endpoints only and network rules will not be applied." + "description": "Optional. A value that indicates whether the queue is to be partitioned across multiple message brokers." } }, - "defaultAction": { + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "lockDuration": { "type": "string", - "allowedValues": [ - "Allow", - "Deny" - ], "nullable": true, "metadata": { - "description": "Optional. Default Action for Network Rule Set. Default is \"Allow\". It will not be set if publicNetworkAccess is \"Disabled\". Otherwise, it will be set to \"Deny\" if ipRules or virtualNetworkRules are being used." + "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." } }, - "trustedServiceAccessEnabled": { + "maxDeliveryCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The maximum delivery count. A message is automatically deadlettered after this number of deliveries. default value is 10." + } + }, + "maxSizeInMegabytes": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The maximum size of the queue in megabytes, which is the size of memory allocated for the queue. Default is 1024." + } + }, + "requiresDuplicateDetection": { "type": "bool", "nullable": true, "metadata": { - "description": "Optional. Value that indicates whether Trusted Service Access is enabled or not. Default is \"true\". It will not be set if publicNetworkAccess is \"Disabled\"." + "description": "Optional. A value indicating if this queue requires duplicate detection." } }, - "ipRules": { - "type": "array", - "items": { - "type": "object", - "properties": { - "action": { - "type": "string", - "allowedValues": [ - "Allow", - "Deny" - ], - "metadata": { - "description": "Required. The IP filter action." - } - }, - "ipMask": { - "type": "string", - "metadata": { - "description": "Required. The IP mask." - } - } - } - }, + "requiresSession": { + "type": "bool", "nullable": true, "metadata": { - "description": "Optional. List of IpRules. It will not be set if publicNetworkAccess is \"Disabled\". Otherwise, when used, defaultAction will be set to \"Deny\"." + "description": "Optional. A value that indicates whether the queue supports the concept of sessions." } }, - "virtualNetworkRules": { + "roleAssignments": { "type": "array", "items": { - "type": "object", - "properties": { - "ignoreMissingVnetServiceEndpoint": { - "type": "bool", - "metadata": { - "description": "Required. The virtual network rule name." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. The ID of the subnet." - } - } - } + "$ref": "#/definitions/roleAssignmentType" }, "nullable": true, "metadata": { - "description": "Optional. List virtual network rules. It will not be set if publicNetworkAccess is \"Disabled\". Otherwise, when used, defaultAction will be set to \"Deny\"." + "description": "Optional. Array of role assignments to create." + } + }, + "status": { + "type": "string", + "allowedValues": [ + "Active", + "Creating", + "Deleting", + "Disabled", + "ReceiveDisabled", + "Renaming", + "Restoring", + "SendDisabled", + "Unknown" + ], + "nullable": true, + "metadata": { + "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "queueType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the queue." - } + "topicType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the topic." + } + }, + "authorizationRules": { + "type": "array", + "items": { + "$ref": "#/definitions/authorizationRuleType" }, - "autoDeleteOnIdle": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8061 timeSpan idle interval after which the queue is automatically deleted. The minimum duration is 5 minutes (PT5M)." - } - }, - "forwardDeadLetteredMessagesTo": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Queue/Topic name to forward the Dead Letter message." - } - }, - "forwardTo": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Queue/Topic name to forward the messages." - } - }, - "maxMessageSizeInKilobytes": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. Maximum size (in KB) of the message payload that can be accepted by the queue. This property is only used in Premium today and default is 1024." - } - }, - "authorizationRules": { - "$ref": "#/definitions/authorizationRuleType", - "nullable": true, - "metadata": { - "description": "Optional. Authorization Rules for the Service Bus Queue." - } - }, - "deadLetteringOnMessageExpiration": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether this queue has dead letter support when a message expires." - } - }, - "defaultMessageTimeToLive": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "duplicateDetectionHistoryTimeWindow": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes." - } - }, - "enableBatchedOperations": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Value that indicates whether server-side batched operations are enabled." - } - }, - "enableExpress": { - "type": "bool", - "nullable": true, - "metadata": { - "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. This property is only used if the `service-bus/namespace` sku is Premium." - } - }, - "enablePartitioning": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether the queue is to be partitioned across multiple message brokers." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "nullable": true, - "metadata": { - "description": "Optional. The lock settings of the service." - } - }, - "lockDuration": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "maxDeliveryCount": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The maximum delivery count. A message is automatically deadlettered after this number of deliveries. default value is 10." - } - }, - "maxSizeInMegabytes": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The maximum size of the queue in megabytes, which is the size of memory allocated for the queue. Default is 1024." - } - }, - "requiresDuplicateDetection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value indicating if this queue requires duplicate detection." - } + "nullable": true, + "metadata": { + "description": "Optional. Authorization Rules for the Service Bus Topic." + } + }, + "autoDeleteOnIdle": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan idle interval after which the topic is automatically deleted. The minimum duration is 5 minutes." + } + }, + "defaultMessageTimeToLive": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + }, + "duplicateDetectionHistoryTimeWindow": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes." + } + }, + "enableBatchedOperations": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Value that indicates whether server-side batched operations are enabled." + } + }, + "enableExpress": { + "type": "bool", + "nullable": true, + "metadata": { + "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. This property is only used if the `service-bus/namespace` sku is Premium." + } + }, + "enablePartitioning": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether the topic is to be partitioned across multiple message brokers." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "maxMessageSizeInKilobytes": { + "type": "int", + "nullable": true, + "metadata": { + "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." + } + }, + "maxSizeInMegabytes": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The maximum size of the topic in megabytes, which is the size of memory allocated for the topic. Default is 1024." + } + }, + "requiresDuplicateDetection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value indicating if this topic requires duplicate detection." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" }, - "requiresSession": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether the queue supports the concept of sessions." - } + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "status": { + "type": "string", + "allowedValues": [ + "Active", + "Creating", + "Deleting", + "Disabled", + "ReceiveDisabled", + "Renaming", + "Restoring", + "SendDisabled", + "Unknown" + ], + "nullable": true, + "metadata": { + "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." + } + }, + "supportOrdering": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Value that indicates whether the topic supports ordering." + } + }, + "subscriptions": { + "type": "array", + "items": { + "$ref": "#/definitions/subscriptionType" }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "nullable": true, - "metadata": { - "description": "Optional. Array of role assignments to create." - } + "nullable": true, + "metadata": { + "description": "Optional. The subscriptions of the topic." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "_1.privateEndpointCustomDnsConfigType": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" }, - "status": { - "type": "string", - "allowedValues": [ - "Active", - "Creating", - "Deleting", - "Disabled", - "ReceiveDisabled", - "Renaming", - "Restoring", - "SendDisabled", - "Unknown" - ], - "nullable": true, - "metadata": { - "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." - } + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "topicType": { - "type": "array", - "items": { - "type": "object", + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the topic." - } - }, - "authorizationRules": { - "$ref": "#/definitions/authorizationRuleType", - "nullable": true, - "metadata": { - "description": "Optional. Authorization Rules for the Service Bus Topic." - } - }, - "autoDeleteOnIdle": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timespan idle interval after which the topic is automatically deleted. The minimum duration is 5 minutes." - } - }, - "defaultMessageTimeToLive": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "duplicateDetectionHistoryTimeWindow": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes." - } - }, - "enableBatchedOperations": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Value that indicates whether server-side batched operations are enabled." - } - }, - "enableExpress": { - "type": "bool", - "nullable": true, - "metadata": { - "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. This property is only used if the `service-bus/namespace` sku is Premium." - } - }, - "enablePartitioning": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether the topic is to be partitioned across multiple message brokers." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "nullable": true, - "metadata": { - "description": "Optional. The lock settings of the service." - } - }, - "maxMessageSizeInKilobytes": { - "type": "int", - "nullable": true, - "metadata": { - "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." - } - }, - "maxSizeInMegabytes": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The maximum size of the topic in megabytes, which is the size of memory allocated for the topic. Default is 1024." - } - }, - "requiresDuplicateDetection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value indicating if this topic requires duplicate detection." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "nullable": true, - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "status": { - "type": "string", - "allowedValues": [ - "Active", - "Creating", - "Deleting", - "Disabled", - "ReceiveDisabled", - "Renaming", - "Restoring", - "SendDisabled", - "Unknown" - ], - "nullable": true, - "metadata": { - "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "supportOrdering": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Value that indicates whether the topic supports ordering." + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS Zone Group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } } }, - "subscriptions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the service bus namespace topic subscription." - } - }, - "autoDeleteOnIdle": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes." - } - }, - "clientAffineProperties": { - "type": "object", - "properties": { - "clientId": { - "type": "string", - "metadata": { - "description": "Required. Indicates the Client ID of the application that created the client-affine subscription." - } - }, - "isDurable": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is durable or not." - } - }, - "isShared": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is shared or not." - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The properties that are associated with a subscription that is client-affine." - } - }, - "deadLetteringOnMessageExpiration": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." - } - }, - "deadLetteringOnFilterEvaluationExceptions": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." - } - }, - "defaultMessageTimeToLive": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timespan idle interval after which the message expires. The minimum duration is 5 minutes." - } - }, - "duplicateDetectionHistoryTimeWindow": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timespan that defines the duration of the duplicate detection history. The default value is 10 minutes." - } - }, - "enableBatchedOperations": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether server-side batched operations are enabled." - } - }, - "forwardDeadLetteredMessagesTo": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." - } - }, - "forwardTo": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." - } - }, - "isClientAffine": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether the subscription supports the concept of session." - } - }, - "lockDuration": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "maxDeliveryCount": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. Number of maximum deliveries. A message is automatically deadlettered after this number of deliveries. Default value is 10." - } - }, - "requiresSession": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether the subscription supports the concept of session." - } - }, - "status": { - "type": "string", - "allowedValues": [ - "Active", - "Creating", - "Deleting", - "Disabled", - "ReceiveDisabled", - "Renaming", - "Restoring", - "SendDisabled", - "Unknown" - ], - "nullable": true, - "metadata": { - "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." - } + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a customer-managed key.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "privateEndpointSingleServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private Endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the Private Endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the Private Endpoint for. For example \"vault\" for a Key Vault Private Endpoint." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS Zone Group to configure for the Private Endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the Private Endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the Private Endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/Resource Groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like 'vault' for key vault).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "subscriptionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the service bus namespace topic subscription." + } + }, + "autoDeleteOnIdle": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes." + } + }, + "clientAffineProperties": { + "type": "object", + "properties": { + "clientId": { + "type": "string", + "metadata": { + "description": "Required. Indicates the Client ID of the application that created the client-affine subscription." + } + }, + "isDurable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is durable or not." } }, - "nullable": true, - "metadata": { - "description": "Optional. The subscriptions of the topic." + "isShared": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is shared or not." + } } + }, + "nullable": true, + "metadata": { + "description": "Optional. The properties that are associated with a subscription that is client-affine." + } + }, + "deadLetteringOnMessageExpiration": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." + } + }, + "deadLetteringOnFilterEvaluationExceptions": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." + } + }, + "defaultMessageTimeToLive": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan idle interval after which the message expires. The minimum duration is 5 minutes." + } + }, + "duplicateDetectionHistoryTimeWindow": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan that defines the duration of the duplicate detection history. The default value is 10 minutes." + } + }, + "enableBatchedOperations": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether server-side batched operations are enabled." + } + }, + "forwardDeadLetteredMessagesTo": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." + } + }, + "forwardTo": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." + } + }, + "isClientAffine": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether the subscription supports the concept of session." + } + }, + "lockDuration": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + }, + "maxDeliveryCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Number of maximum deliveries. A message is automatically deadlettered after this number of deliveries. Default value is 10." + } + }, + "requiresSession": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether the subscription supports the concept of session." + } + }, + "status": { + "type": "string", + "allowedValues": [ + "Active", + "Creating", + "Deleting", + "Disabled", + "ReceiveDisabled", + "Renaming", + "Restoring", + "SendDisabled", + "Unknown" + ], + "nullable": true, + "metadata": { + "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "topic/main.bicep" + } + } } }, "parameters": { @@ -1142,7 +1219,7 @@ "capacity": 2 }, "metadata": { - "description": "Required. The SKU of the Service Bus Namespace. Defaulted to Premium for ZoneRedundant configurations by default." + "description": "Optional. The SKU of the Service Bus Namespace. Defaulted to Premium for ZoneRedundant configurations by default." } }, "zoneRedundant": { @@ -1179,7 +1256,10 @@ } }, "authorizationRules": { - "$ref": "#/definitions/authorizationRuleType", + "type": "array", + "items": { + "$ref": "#/definitions/authorizationRuleType" + }, "defaultValue": [ { "name": "RootManageSharedAccessKey", @@ -1196,36 +1276,48 @@ }, "migrationConfiguration": { "$ref": "#/definitions/migrationConfigurationsType", + "nullable": true, "metadata": { "description": "Optional. The migration configuration." } }, "disasterRecoveryConfig": { "$ref": "#/definitions/disasterRecoveryConfigType", + "nullable": true, "metadata": { "description": "Optional. The disaster recovery configuration." } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -1244,7 +1336,11 @@ } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointSingleServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } @@ -1278,14 +1374,20 @@ } }, "queues": { - "$ref": "#/definitions/queueType", + "type": "array", + "items": { + "$ref": "#/definitions/queueType" + }, "nullable": true, "metadata": { "description": "Optional. The queues to create in the service bus namespace." } }, "topics": { - "$ref": "#/definitions/topicType", + "type": "array", + "items": { + "$ref": "#/definitions/topicType" + }, "nullable": true, "metadata": { "description": "Optional. The topics to create in the service bus namespace." @@ -1293,6 +1395,7 @@ }, "customerManagedKey": { "$ref": "#/definitions/customerManagedKeyType", + "nullable": true, "metadata": { "description": "Optional. The customer managed key definition." } @@ -1313,8 +1416,8 @@ "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" } ], - "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", - "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourcesIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned, UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', 'None')), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", "builtInRoleNames": { "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')]", @@ -1509,8 +1612,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "16659347344675880024" + "version": "0.30.23.60470", + "templateHash": "4728331591356881277" }, "name": "Service Bus Namespace Authorization Rules", "description": "This module deploys a Service Bus Namespace Authorization Rule.", @@ -1613,8 +1716,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2437567647402328568" + "version": "0.30.23.60470", + "templateHash": "1218226237647695558" }, "name": "Service Bus Namespace Disaster Recovery Configs", "description": "This module deploys a Service Bus Namespace Disaster Recovery Config", @@ -1718,8 +1821,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5021121087195745079" + "version": "0.30.23.60470", + "templateHash": "16589713685358551002" }, "name": "Service Bus Namespace Migration Configuration", "description": "This module deploys a Service Bus Namespace Migration Configuration.", @@ -1823,8 +1926,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "18220065019802173538" + "version": "0.30.23.60470", + "templateHash": "10915287587573662426" }, "name": "Service Bus Namespace Network Rule Sets", "description": "This module deploys a ServiceBus Namespace Network Rule Set.", @@ -1889,7 +1992,7 @@ "name": "networkRules", "count": "[length(parameters('virtualNetworkRules'))]", "input": { - "ignoreMissingVnetServiceEndpoint": "[if(contains(parameters('virtualNetworkRules')[copyIndex('networkRules')], 'ignoreMissingVnetServiceEndpoint'), parameters('virtualNetworkRules')[copyIndex('networkRules')].ignoreMissingVnetServiceEndpoint, null())]", + "ignoreMissingVnetServiceEndpoint": "[tryGet(parameters('virtualNetworkRules')[copyIndex('networkRules')], 'ignoreMissingVnetServiceEndpoint')]", "subnet": "[if(contains(parameters('virtualNetworkRules')[copyIndex('networkRules')], 'subnetResourceId'), createObject('id', parameters('virtualNetworkRules')[copyIndex('networkRules')].subnetResourceId), null())]" } } @@ -2023,8 +2126,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12442268068778335924" + "version": "0.30.23.60470", + "templateHash": "3861797593527725325" }, "name": "Service Bus Namespace Queue", "description": "This module deploys a Service Bus Namespace Queue.", @@ -2038,96 +2141,103 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." } }, - "kind": { + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { "type": "string", "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" + "2.0" ], "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Optional. Version of the condition." } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -2279,12 +2389,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -2411,8 +2526,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13378473188831787359" + "version": "0.30.23.60470", + "templateHash": "13793175890494658919" }, "name": "Service Bus Namespace Queue Authorization Rules", "description": "This module deploys a Service Bus Namespace Queue Authorization Rule.", @@ -2592,14 +2707,159 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "782028791267114581" + "version": "0.30.23.60470", + "templateHash": "11839100867387060454" + }, + "name": "Service Bus Namespace Topic", + "description": "This module deploys a Service Bus Namespace Topic.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "subscriptionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the service bus namespace topic subscription." + } + }, + "autoDeleteOnIdle": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes." + } + }, + "clientAffineProperties": { + "type": "object", + "properties": { + "clientId": { + "type": "string", + "metadata": { + "description": "Required. Indicates the Client ID of the application that created the client-affine subscription." + } + }, + "isDurable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is durable or not." + } + }, + "isShared": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is shared or not." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The properties that are associated with a subscription that is client-affine." + } + }, + "deadLetteringOnMessageExpiration": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." + } + }, + "deadLetteringOnFilterEvaluationExceptions": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." + } + }, + "defaultMessageTimeToLive": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan idle interval after which the message expires. The minimum duration is 5 minutes." + } + }, + "duplicateDetectionHistoryTimeWindow": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan that defines the duration of the duplicate detection history. The default value is 10 minutes." + } + }, + "enableBatchedOperations": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether server-side batched operations are enabled." + } + }, + "forwardDeadLetteredMessagesTo": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." + } + }, + "forwardTo": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." + } + }, + "isClientAffine": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether the subscription supports the concept of session." + } + }, + "lockDuration": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + }, + "maxDeliveryCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Number of maximum deliveries. A message is automatically deadlettered after this number of deliveries. Default value is 10." + } + }, + "requiresSession": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether the subscription supports the concept of session." + } + }, + "status": { + "type": "string", + "allowedValues": [ + "Active", + "Creating", + "Deleting", + "Disabled", + "ReceiveDisabled", + "Renaming", + "Restoring", + "SendDisabled", + "Unknown" + ], + "nullable": true, + "metadata": { + "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." + } + } + }, + "metadata": { + "__bicep_export!": true + } }, - "name": "Service Bus Namespace Topic", - "description": "This module deploys a Service Bus Namespace Topic.", - "owner": "Azure/module-maintainers" - }, - "definitions": { "lockType": { "type": "object", "properties": { @@ -2623,225 +2883,87 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } - } - }, - "nullable": true - }, - "subscriptionsType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the service bus namespace topic subscription." - } - }, - "autoDeleteOnIdle": { - "type": "string", - "metadata": { - "description": "Optional. ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes." - } - }, - "clientAffineProperties": { - "type": "object", - "properties": { - "clientId": { - "type": "string", - "metadata": { - "description": "Required. Indicates the Client ID of the application that created the client-affine subscription." - } - }, - "isDurable": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is durable or not." - } - }, - "isShared": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is shared or not." - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The properties that are associated with a subscription that is client-affine." - } - }, - "deadLetteringOnMessageExpiration": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." - } - }, - "deadLetteringOnFilterEvaluationExceptions": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." - } - }, - "defaultMessageTimeToLive": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timespan idle interval after which the message expires. The minimum duration is 5 minutes." - } - }, - "duplicateDetectionHistoryTimeWindow": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timespan that defines the duration of the duplicate detection history. The default value is 10 minutes." - } - }, - "enableBatchedOperations": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether server-side batched operations are enabled." - } - }, - "forwardDeadLetteredMessagesTo": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." - } - }, - "forwardTo": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." - } - }, - "isClientAffine": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether the subscription supports the concept of session." - } - }, - "lockDuration": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "maxDeliveryCount": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. Number of maximum deliveries. A message is automatically deadlettered after this number of deliveries. Default value is 10." - } - }, - "requiresSession": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether the subscription supports the concept of session." - } - }, - "status": { - "type": "string", - "allowedValues": [ - "Active", - "Creating", - "Deleting", - "Disabled", - "ReceiveDisabled", - "Renaming", - "Restoring", - "SendDisabled", - "Unknown" - ], - "nullable": true, - "metadata": { - "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." - } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -2951,37 +3073,34 @@ }, "authorizationRules": { "type": "array", - "defaultValue": [ - { - "name": "RootManageSharedAccessKey", - "properties": { - "rights": [ - "Listen", - "Manage", - "Send" - ] - } - } - ], + "defaultValue": [], "metadata": { "description": "Optional. Authorization Rules for the Service Bus Topic." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } }, "subscriptions": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/subscriptionType" + }, + "nullable": true, "metadata": { "description": "Optional. The subscriptions of the topic." } @@ -3081,7 +3200,9 @@ "name": { "value": "[parameters('authorizationRules')[copyIndex()].name]" }, - "rights": "[if(contains(parameters('authorizationRules')[copyIndex()], 'rights'), createObject('value', parameters('authorizationRules')[copyIndex()].rights), createObject('value', createArray()))]" + "rights": { + "value": "[coalesce(tryGet(parameters('authorizationRules')[copyIndex()], 'rights'), createArray())]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -3089,8 +3210,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6843568331497160185" + "version": "0.30.23.60470", + "templateHash": "1348283370469099109" }, "name": "Service Bus Namespace Topic Authorization Rules", "description": "This module deploys a Service Bus Namespace Topic Authorization Rule.", @@ -3239,8 +3360,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13559505347925945415" + "version": "0.30.23.60470", + "templateHash": "2560238010859719670" }, "name": "Service Bus Namespace Topic Subscription", "description": "This module deploys a Service Bus Namespace Topic Subscription.", diff --git a/avm/res/service-bus/namespace/migration-configuration/main.json b/avm/res/service-bus/namespace/migration-configuration/main.json index 47cb3b3ead..58dfcc663d 100644 --- a/avm/res/service-bus/namespace/migration-configuration/main.json +++ b/avm/res/service-bus/namespace/migration-configuration/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5021121087195745079" + "version": "0.30.23.60470", + "templateHash": "16589713685358551002" }, "name": "Service Bus Namespace Migration Configuration", "description": "This module deploys a Service Bus Namespace Migration Configuration.", diff --git a/avm/res/service-bus/namespace/network-rule-set/main.bicep b/avm/res/service-bus/namespace/network-rule-set/main.bicep index b2fa51cb5e..4930565240 100644 --- a/avm/res/service-bus/namespace/network-rule-set/main.bicep +++ b/avm/res/service-bus/namespace/network-rule-set/main.bicep @@ -32,9 +32,7 @@ param ipRules array = [] var networkRules = [ for (virtualNetworkRule, index) in virtualNetworkRules: { - ignoreMissingVnetServiceEndpoint: contains(virtualNetworkRule, 'ignoreMissingVnetServiceEndpoint') - ? virtualNetworkRule.ignoreMissingVnetServiceEndpoint - : null + ignoreMissingVnetServiceEndpoint: virtualNetworkRule.?ignoreMissingVnetServiceEndpoint subnet: contains(virtualNetworkRule, 'subnetResourceId') ? { id: virtualNetworkRule.subnetResourceId diff --git a/avm/res/service-bus/namespace/network-rule-set/main.json b/avm/res/service-bus/namespace/network-rule-set/main.json index 5f9ac47d13..2bfebce5e6 100644 --- a/avm/res/service-bus/namespace/network-rule-set/main.json +++ b/avm/res/service-bus/namespace/network-rule-set/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "18220065019802173538" + "version": "0.30.23.60470", + "templateHash": "10915287587573662426" }, "name": "Service Bus Namespace Network Rule Sets", "description": "This module deploys a ServiceBus Namespace Network Rule Set.", @@ -70,7 +70,7 @@ "name": "networkRules", "count": "[length(parameters('virtualNetworkRules'))]", "input": { - "ignoreMissingVnetServiceEndpoint": "[if(contains(parameters('virtualNetworkRules')[copyIndex('networkRules')], 'ignoreMissingVnetServiceEndpoint'), parameters('virtualNetworkRules')[copyIndex('networkRules')].ignoreMissingVnetServiceEndpoint, null())]", + "ignoreMissingVnetServiceEndpoint": "[tryGet(parameters('virtualNetworkRules')[copyIndex('networkRules')], 'ignoreMissingVnetServiceEndpoint')]", "subnet": "[if(contains(parameters('virtualNetworkRules')[copyIndex('networkRules')], 'subnetResourceId'), createObject('id', parameters('virtualNetworkRules')[copyIndex('networkRules')].subnetResourceId), null())]" } } diff --git a/avm/res/service-bus/namespace/queue/README.md b/avm/res/service-bus/namespace/queue/README.md index 0c581d4e73..9a321d7ef5 100644 --- a/avm/res/service-bus/namespace/queue/README.md +++ b/avm/res/service-bus/namespace/queue/README.md @@ -7,6 +7,7 @@ This module deploys a Service Bus Namespace Queue. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -365,3 +366,11 @@ Enumerates the possible values for the status of a messaging entity. - Active, D | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/service-bus/namespace/queue/authorization-rule/main.json b/avm/res/service-bus/namespace/queue/authorization-rule/main.json index 2ac613b3a0..7f4595b2c4 100644 --- a/avm/res/service-bus/namespace/queue/authorization-rule/main.json +++ b/avm/res/service-bus/namespace/queue/authorization-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13378473188831787359" + "version": "0.30.23.60470", + "templateHash": "13793175890494658919" }, "name": "Service Bus Namespace Queue Authorization Rules", "description": "This module deploys a Service Bus Namespace Queue Authorization Rule.", diff --git a/avm/res/service-bus/namespace/queue/main.bicep b/avm/res/service-bus/namespace/queue/main.bicep index b6e1097705..b085ce248a 100644 --- a/avm/res/service-bus/namespace/queue/main.bicep +++ b/avm/res/service-bus/namespace/queue/main.bicep @@ -74,11 +74,13 @@ param enableExpress bool = false @description('Optional. Authorization Rules for the Service Bus Queue.') param authorizationRules array = [] +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? var builtInRoleNames = { 'Azure Service Bus Data Owner': subscriptionResourceId( @@ -191,41 +193,3 @@ output resourceId string = queue.id @description('The resource group of the deployed queue.') output resourceGroupName string = resourceGroup().name - -// =============== // -// Definitions // -// =============== // - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/service-bus/namespace/queue/main.json b/avm/res/service-bus/namespace/queue/main.json index 49ba95b068..8cdee33729 100644 --- a/avm/res/service-bus/namespace/queue/main.json +++ b/avm/res/service-bus/namespace/queue/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12442268068778335924" + "version": "0.30.23.60470", + "templateHash": "3861797593527725325" }, "name": "Service Bus Namespace Queue", "description": "This module deploys a Service Bus Namespace Queue.", @@ -36,80 +36,87 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -261,12 +268,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -393,8 +405,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13378473188831787359" + "version": "0.30.23.60470", + "templateHash": "13793175890494658919" }, "name": "Service Bus Namespace Queue Authorization Rules", "description": "This module deploys a Service Bus Namespace Queue Authorization Rule.", diff --git a/avm/res/service-bus/namespace/tests/e2e/encr/main.test.bicep b/avm/res/service-bus/namespace/tests/e2e/encr/main.test.bicep index 9a02d24b0c..7f28c08ba6 100644 --- a/avm/res/service-bus/namespace/tests/e2e/encr/main.test.bicep +++ b/avm/res/service-bus/namespace/tests/e2e/encr/main.test.bicep @@ -64,7 +64,7 @@ module testDeployment '../../../main.bicep' = [ location: resourceLocation managedIdentities: { systemAssigned: false - userAssignedResourcesIds: [ + userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } diff --git a/avm/res/service-bus/namespace/tests/e2e/max/main.test.bicep b/avm/res/service-bus/namespace/tests/e2e/max/main.test.bicep index fcf8d82aee..49c8e10bae 100644 --- a/avm/res/service-bus/namespace/tests/e2e/max/main.test.bicep +++ b/avm/res/service-bus/namespace/tests/e2e/max/main.test.bicep @@ -299,7 +299,7 @@ module testDeployment '../../../main.bicep' = [ ] managedIdentities: { systemAssigned: true - userAssignedResourcesIds: [ + userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } @@ -307,9 +307,5 @@ module testDeployment '../../../main.bicep' = [ publicNetworkAccess: 'Enabled' minimumTlsVersion: '1.2' } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] } ] diff --git a/avm/res/service-bus/namespace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/service-bus/namespace/tests/e2e/waf-aligned/main.test.bicep index 2160534080..3eb6f9aff1 100644 --- a/avm/res/service-bus/namespace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/service-bus/namespace/tests/e2e/waf-aligned/main.test.bicep @@ -66,22 +66,12 @@ module testDeployment '../../../main.bicep' = [ name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } location: resourceLocation - skuObject: { - name: 'Premium' - capacity: 2 - } - premiumMessagingPartitions: 1 tags: { 'hidden-title': 'This is visible in the resource name' Environment: 'Non-Prod' Role: 'DeploymentValidation' } - roleAssignments: [] networkRuleSets: { defaultAction: 'Deny' trustedServiceAccessEnabled: true @@ -193,19 +183,7 @@ module testDeployment '../../../main.bicep' = [ } } ] - managedIdentities: { - systemAssigned: true - userAssignedResourcesIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - disableLocalAuth: true publicNetworkAccess: 'Enabled' - minimumTlsVersion: '1.2' } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] } ] diff --git a/avm/res/service-bus/namespace/topic/README.md b/avm/res/service-bus/namespace/topic/README.md index 7362055d9e..721da36bda 100644 --- a/avm/res/service-bus/namespace/topic/README.md +++ b/avm/res/service-bus/namespace/topic/README.md @@ -7,6 +7,7 @@ This module deploys a Service Bus Namespace Topic. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -72,21 +73,7 @@ Authorization Rules for the Service Bus Topic. - Required: No - Type: array -- Default: - ```Bicep - [ - { - name: 'RootManageSharedAccessKey' - properties: { - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } - } - ] - ``` +- Default: `[]` ### Parameter: `autoDeleteOnIdle` @@ -329,7 +316,184 @@ The subscriptions of the topic. - Required: No - Type: array -- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-subscriptionsname) | string | The name of the service bus namespace topic subscription. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoDeleteOnIdle`](#parameter-subscriptionsautodeleteonidle) | string | ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes. | +| [`clientAffineProperties`](#parameter-subscriptionsclientaffineproperties) | object | The properties that are associated with a subscription that is client-affine. | +| [`deadLetteringOnFilterEvaluationExceptions`](#parameter-subscriptionsdeadletteringonfilterevaluationexceptions) | bool | A value that indicates whether a subscription has dead letter support when a message expires. | +| [`deadLetteringOnMessageExpiration`](#parameter-subscriptionsdeadletteringonmessageexpiration) | bool | A value that indicates whether a subscription has dead letter support when a message expires. | +| [`defaultMessageTimeToLive`](#parameter-subscriptionsdefaultmessagetimetolive) | string | ISO 8601 timespan idle interval after which the message expires. The minimum duration is 5 minutes. | +| [`duplicateDetectionHistoryTimeWindow`](#parameter-subscriptionsduplicatedetectionhistorytimewindow) | string | ISO 8601 timespan that defines the duration of the duplicate detection history. The default value is 10 minutes. | +| [`enableBatchedOperations`](#parameter-subscriptionsenablebatchedoperations) | bool | A value that indicates whether server-side batched operations are enabled. | +| [`forwardDeadLetteredMessagesTo`](#parameter-subscriptionsforwarddeadletteredmessagesto) | string | The name of the recipient entity to which all the messages sent to the subscription are forwarded to. | +| [`forwardTo`](#parameter-subscriptionsforwardto) | string | The name of the recipient entity to which all the messages sent to the subscription are forwarded to. | +| [`isClientAffine`](#parameter-subscriptionsisclientaffine) | bool | A value that indicates whether the subscription supports the concept of session. | +| [`lockDuration`](#parameter-subscriptionslockduration) | string | 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`](#parameter-subscriptionsmaxdeliverycount) | int | Number of maximum deliveries. A message is automatically deadlettered after this number of deliveries. Default value is 10. | +| [`requiresSession`](#parameter-subscriptionsrequiressession) | bool | A value that indicates whether the subscription supports the concept of session. | +| [`status`](#parameter-subscriptionsstatus) | string | Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown. | + +### Parameter: `subscriptions.name` + +The name of the service bus namespace topic subscription. + +- Required: Yes +- Type: string + +### Parameter: `subscriptions.autoDeleteOnIdle` + +ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes. + +- Required: No +- Type: string + +### Parameter: `subscriptions.clientAffineProperties` + +The properties that are associated with a subscription that is client-affine. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`clientId`](#parameter-subscriptionsclientaffinepropertiesclientid) | string | Indicates the Client ID of the application that created the client-affine subscription. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`isDurable`](#parameter-subscriptionsclientaffinepropertiesisdurable) | bool | For client-affine subscriptions, this value indicates whether the subscription is durable or not. | +| [`isShared`](#parameter-subscriptionsclientaffinepropertiesisshared) | bool | For client-affine subscriptions, this value indicates whether the subscription is shared or not. | + +### Parameter: `subscriptions.clientAffineProperties.clientId` + +Indicates the Client ID of the application that created the client-affine subscription. + +- Required: Yes +- Type: string + +### Parameter: `subscriptions.clientAffineProperties.isDurable` + +For client-affine subscriptions, this value indicates whether the subscription is durable or not. + +- Required: No +- Type: bool + +### Parameter: `subscriptions.clientAffineProperties.isShared` + +For client-affine subscriptions, this value indicates whether the subscription is shared or not. + +- Required: No +- Type: bool + +### Parameter: `subscriptions.deadLetteringOnFilterEvaluationExceptions` + +A value that indicates whether a subscription has dead letter support when a message expires. + +- Required: No +- Type: bool + +### Parameter: `subscriptions.deadLetteringOnMessageExpiration` + +A value that indicates whether a subscription has dead letter support when a message expires. + +- Required: No +- Type: bool + +### Parameter: `subscriptions.defaultMessageTimeToLive` + +ISO 8601 timespan idle interval after which the message expires. The minimum duration is 5 minutes. + +- Required: No +- Type: string + +### Parameter: `subscriptions.duplicateDetectionHistoryTimeWindow` + +ISO 8601 timespan that defines the duration of the duplicate detection history. The default value is 10 minutes. + +- Required: No +- Type: string + +### Parameter: `subscriptions.enableBatchedOperations` + +A value that indicates whether server-side batched operations are enabled. + +- Required: No +- Type: bool + +### Parameter: `subscriptions.forwardDeadLetteredMessagesTo` + +The name of the recipient entity to which all the messages sent to the subscription are forwarded to. + +- Required: No +- Type: string + +### Parameter: `subscriptions.forwardTo` + +The name of the recipient entity to which all the messages sent to the subscription are forwarded to. + +- Required: No +- Type: string + +### Parameter: `subscriptions.isClientAffine` + +A value that indicates whether the subscription supports the concept of session. + +- Required: No +- Type: bool + +### Parameter: `subscriptions.lockDuration` + +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. + +- Required: No +- Type: string + +### Parameter: `subscriptions.maxDeliveryCount` + +Number of maximum deliveries. A message is automatically deadlettered after this number of deliveries. Default value is 10. + +- Required: No +- Type: int + +### Parameter: `subscriptions.requiresSession` + +A value that indicates whether the subscription supports the concept of session. + +- Required: No +- Type: bool + +### Parameter: `subscriptions.status` + +Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Active' + 'Creating' + 'Deleting' + 'Disabled' + 'ReceiveDisabled' + 'Renaming' + 'Restoring' + 'SendDisabled' + 'Unknown' + ] + ``` ### Parameter: `supportOrdering` @@ -346,3 +510,11 @@ Value that indicates whether the topic supports ordering. | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/service-bus/namespace/topic/authorization-rule/main.json b/avm/res/service-bus/namespace/topic/authorization-rule/main.json index 60d8ebef9f..f3ac22d34d 100644 --- a/avm/res/service-bus/namespace/topic/authorization-rule/main.json +++ b/avm/res/service-bus/namespace/topic/authorization-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6843568331497160185" + "version": "0.30.23.60470", + "templateHash": "1348283370469099109" }, "name": "Service Bus Namespace Topic Authorization Rules", "description": "This module deploys a Service Bus Namespace Topic Authorization Rule.", diff --git a/avm/res/service-bus/namespace/topic/main.bicep b/avm/res/service-bus/namespace/topic/main.bicep index 2009633393..138d36ad3f 100644 --- a/avm/res/service-bus/namespace/topic/main.bicep +++ b/avm/res/service-bus/namespace/topic/main.bicep @@ -57,27 +57,18 @@ param enablePartitioning bool = false param enableExpress bool = false @description('Optional. Authorization Rules for the Service Bus Topic.') -param authorizationRules array = [ - { - name: 'RootManageSharedAccessKey' - properties: { - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } - } -] +param authorizationRules array = [] +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. The subscriptions of the topic.') -param subscriptions array = [] +param subscriptions subscriptionType[]? var builtInRoleNames = { 'Azure Service Bus Data Owner': subscriptionResourceId( @@ -151,7 +142,7 @@ module topic_authorizationRules 'authorization-rule/main.bicep' = [ namespaceName: namespaceName topicName: topic.name name: authorizationRule.name - rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + rights: authorizationRule.?rights ?? [] } } ] @@ -221,46 +212,13 @@ output resourceGroupName string = resourceGroup().name // Definitions // // =============== // -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type subscriptionsType = { +@export() +type subscriptionType = { @description('Required. The name of the service bus namespace topic subscription.') name: string @description('Optional. ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes.') - autoDeleteOnIdle: string + autoDeleteOnIdle: string? @description('Optional. The properties that are associated with a subscription that is client-affine.') clientAffineProperties: { @@ -318,4 +276,4 @@ type subscriptionsType = { | 'Deleting' | 'Renaming' | 'Unknown')? -}[]? +} diff --git a/avm/res/service-bus/namespace/topic/main.json b/avm/res/service-bus/namespace/topic/main.json index f037f5762d..7e24b4bdd8 100644 --- a/avm/res/service-bus/namespace/topic/main.json +++ b/avm/res/service-bus/namespace/topic/main.json @@ -5,14 +5,159 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "782028791267114581" + "version": "0.30.23.60470", + "templateHash": "11839100867387060454" }, "name": "Service Bus Namespace Topic", "description": "This module deploys a Service Bus Namespace Topic.", "owner": "Azure/module-maintainers" }, "definitions": { + "subscriptionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the service bus namespace topic subscription." + } + }, + "autoDeleteOnIdle": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes." + } + }, + "clientAffineProperties": { + "type": "object", + "properties": { + "clientId": { + "type": "string", + "metadata": { + "description": "Required. Indicates the Client ID of the application that created the client-affine subscription." + } + }, + "isDurable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is durable or not." + } + }, + "isShared": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is shared or not." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The properties that are associated with a subscription that is client-affine." + } + }, + "deadLetteringOnMessageExpiration": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." + } + }, + "deadLetteringOnFilterEvaluationExceptions": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." + } + }, + "defaultMessageTimeToLive": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan idle interval after which the message expires. The minimum duration is 5 minutes." + } + }, + "duplicateDetectionHistoryTimeWindow": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. ISO 8601 timespan that defines the duration of the duplicate detection history. The default value is 10 minutes." + } + }, + "enableBatchedOperations": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether server-side batched operations are enabled." + } + }, + "forwardDeadLetteredMessagesTo": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." + } + }, + "forwardTo": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." + } + }, + "isClientAffine": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether the subscription supports the concept of session." + } + }, + "lockDuration": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + }, + "maxDeliveryCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Number of maximum deliveries. A message is automatically deadlettered after this number of deliveries. Default value is 10." + } + }, + "requiresSession": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. A value that indicates whether the subscription supports the concept of session." + } + }, + "status": { + "type": "string", + "allowedValues": [ + "Active", + "Creating", + "Deleting", + "Disabled", + "ReceiveDisabled", + "Renaming", + "Restoring", + "SendDisabled", + "Unknown" + ], + "nullable": true, + "metadata": { + "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, "lockType": { "type": "object", "properties": { @@ -36,225 +181,87 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } - } - }, - "nullable": true - }, - "subscriptionsType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the service bus namespace topic subscription." - } - }, - "autoDeleteOnIdle": { - "type": "string", - "metadata": { - "description": "Optional. ISO 8601 timespan idle interval after which the syubscription is automatically deleted. The minimum duration is 5 minutes." - } - }, - "clientAffineProperties": { - "type": "object", - "properties": { - "clientId": { - "type": "string", - "metadata": { - "description": "Required. Indicates the Client ID of the application that created the client-affine subscription." - } - }, - "isDurable": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is durable or not." - } - }, - "isShared": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. For client-affine subscriptions, this value indicates whether the subscription is shared or not." - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The properties that are associated with a subscription that is client-affine." - } - }, - "deadLetteringOnMessageExpiration": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." - } - }, - "deadLetteringOnFilterEvaluationExceptions": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether a subscription has dead letter support when a message expires." - } - }, - "defaultMessageTimeToLive": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timespan idle interval after which the message expires. The minimum duration is 5 minutes." - } - }, - "duplicateDetectionHistoryTimeWindow": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. ISO 8601 timespan that defines the duration of the duplicate detection history. The default value is 10 minutes." - } - }, - "enableBatchedOperations": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether server-side batched operations are enabled." - } - }, - "forwardDeadLetteredMessagesTo": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." - } - }, - "forwardTo": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the recipient entity to which all the messages sent to the subscription are forwarded to." - } - }, - "isClientAffine": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether the subscription supports the concept of session." - } - }, - "lockDuration": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "maxDeliveryCount": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. Number of maximum deliveries. A message is automatically deadlettered after this number of deliveries. Default value is 10." - } - }, - "requiresSession": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. A value that indicates whether the subscription supports the concept of session." - } - }, - "status": { - "type": "string", - "allowedValues": [ - "Active", - "Creating", - "Deleting", - "Disabled", - "ReceiveDisabled", - "Renaming", - "Restoring", - "SendDisabled", - "Unknown" - ], - "nullable": true, - "metadata": { - "description": "Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown." - } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -364,37 +371,34 @@ }, "authorizationRules": { "type": "array", - "defaultValue": [ - { - "name": "RootManageSharedAccessKey", - "properties": { - "rights": [ - "Listen", - "Manage", - "Send" - ] - } - } - ], + "defaultValue": [], "metadata": { "description": "Optional. Authorization Rules for the Service Bus Topic." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } }, "subscriptions": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/subscriptionType" + }, + "nullable": true, "metadata": { "description": "Optional. The subscriptions of the topic." } @@ -494,7 +498,9 @@ "name": { "value": "[parameters('authorizationRules')[copyIndex()].name]" }, - "rights": "[if(contains(parameters('authorizationRules')[copyIndex()], 'rights'), createObject('value', parameters('authorizationRules')[copyIndex()].rights), createObject('value', createArray()))]" + "rights": { + "value": "[coalesce(tryGet(parameters('authorizationRules')[copyIndex()], 'rights'), createArray())]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -502,8 +508,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6843568331497160185" + "version": "0.30.23.60470", + "templateHash": "1348283370469099109" }, "name": "Service Bus Namespace Topic Authorization Rules", "description": "This module deploys a Service Bus Namespace Topic Authorization Rule.", @@ -652,8 +658,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13559505347925945415" + "version": "0.30.23.60470", + "templateHash": "2560238010859719670" }, "name": "Service Bus Namespace Topic Subscription", "description": "This module deploys a Service Bus Namespace Topic Subscription.", diff --git a/avm/res/service-bus/namespace/topic/subscription/main.json b/avm/res/service-bus/namespace/topic/subscription/main.json index 251f6038f1..60ad0f4b59 100644 --- a/avm/res/service-bus/namespace/topic/subscription/main.json +++ b/avm/res/service-bus/namespace/topic/subscription/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "13559505347925945415" + "version": "0.30.23.60470", + "templateHash": "2560238010859719670" }, "name": "Service Bus Namespace Topic Subscription", "description": "This module deploys a Service Bus Namespace Topic Subscription.", diff --git a/avm/res/service-bus/namespace/version.json b/avm/res/service-bus/namespace/version.json index 6b6be93891..a830c3d961 100644 --- a/avm/res/service-bus/namespace/version.json +++ b/avm/res/service-bus/namespace/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.9", + "version": "0.10", "pathFilters": [ "./main.json" ] diff --git a/avm/res/service-networking/traffic-controller/README.md b/avm/res/service-networking/traffic-controller/README.md index c85a18a11b..4c60b78868 100644 --- a/avm/res/service-networking/traffic-controller/README.md +++ b/avm/res/service-networking/traffic-controller/README.md @@ -8,6 +8,7 @@ This module deploys an Application Gateway for Containers - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Notes](#Notes) - [Data Collection](#Data-Collection) @@ -512,7 +513,7 @@ param tags = { | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`frontends`](#parameter-frontends) | array | List of Application Gateway for Containers frontends. | | [`location`](#parameter-location) | string | Location for all Resources. | -| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`lock`](#parameter-lock) | object | The lock settings for all Resources in the solution. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | | [`tags`](#parameter-tags) | object | Resource tags. | @@ -568,7 +569,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -678,7 +679,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -735,7 +736,7 @@ Location for all Resources. ### Parameter: `lock` -The lock settings of the service. +The lock settings for all Resources in the solution. - Required: No - Type: object @@ -891,6 +892,15 @@ Resource tags. | `resourceGroupName` | string | The name of the resource group the resource was created in. | | `resourceId` | string | The resource ID of the Application Gateway for Containers. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.3.0` | Remote reference | + ## Notes > **Limitation**: At this time, the number of associations is limited to 1 (Source: [Application Gateway for Containers associations](https://learn.microsoft.com/en-us/azure/application-gateway/for-containers/application-gateway-for-containers-components#application-gateway-for-containers-associations)) diff --git a/avm/res/service-networking/traffic-controller/association/README.md b/avm/res/service-networking/traffic-controller/association/README.md index 87488abfe2..e706d522f5 100644 --- a/avm/res/service-networking/traffic-controller/association/README.md +++ b/avm/res/service-networking/traffic-controller/association/README.md @@ -21,6 +21,7 @@ This module deploys an Application Gateway for Containers Association | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | Name of the association to create. | +| [`subnetResourceId`](#parameter-subnetresourceid) | string | The resource ID of the subnet to associate with the traffic controller. | **Conditional parameters** @@ -34,12 +35,6 @@ This module deploys an Application Gateway for Containers Association | :-- | :-- | :-- | | [`location`](#parameter-location) | string | Location for all Resources. | -**Reuired parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`subnetResourceId`](#parameter-subnetresourceid) | string | The resource ID of the subnet to associate with the traffic controller. | - ### Parameter: `name` Name of the association to create. @@ -47,6 +42,13 @@ Name of the association to create. - Required: Yes - Type: string +### Parameter: `subnetResourceId` + +The resource ID of the subnet to associate with the traffic controller. + +- Required: Yes +- Type: string + ### Parameter: `trafficControllerName` The name of the parent Application Gateway for Containers instance. Required if the template is used in a standalone deployment. @@ -62,13 +64,6 @@ Location for all Resources. - Type: string - Default: `[resourceGroup().location]` -### Parameter: `subnetResourceId` - -The resource ID of the subnet to associate with the traffic controller. - -- Required: Yes -- Type: string - ## Outputs | Output | Type | Description | diff --git a/avm/res/service-networking/traffic-controller/association/main.bicep b/avm/res/service-networking/traffic-controller/association/main.bicep index 70cc047a29..8837f9de56 100644 --- a/avm/res/service-networking/traffic-controller/association/main.bicep +++ b/avm/res/service-networking/traffic-controller/association/main.bicep @@ -11,7 +11,7 @@ param location string = resourceGroup().location @description('Conditional. The name of the parent Application Gateway for Containers instance. Required if the template is used in a standalone deployment.') param trafficControllerName string -@description('Reuired. The resource ID of the subnet to associate with the traffic controller.') +@description('Required. The resource ID of the subnet to associate with the traffic controller.') param subnetResourceId string // ============== // diff --git a/avm/res/service-networking/traffic-controller/association/main.json b/avm/res/service-networking/traffic-controller/association/main.json index 638bc670f4..97650934a4 100644 --- a/avm/res/service-networking/traffic-controller/association/main.json +++ b/avm/res/service-networking/traffic-controller/association/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "17751059838446450774" + "version": "0.31.34.60546", + "templateHash": "16237699923821445314" }, "name": "Application Gateway for Containers Association", "description": "This module deploys an Application Gateway for Containers Association", @@ -34,7 +34,7 @@ "subnetResourceId": { "type": "string", "metadata": { - "description": "Reuired. The resource ID of the subnet to associate with the traffic controller." + "description": "Required. The resource ID of the subnet to associate with the traffic controller." } } }, diff --git a/avm/res/service-networking/traffic-controller/frontend/main.json b/avm/res/service-networking/traffic-controller/frontend/main.json index f3fb57ad7e..5866bc8d1f 100644 --- a/avm/res/service-networking/traffic-controller/frontend/main.json +++ b/avm/res/service-networking/traffic-controller/frontend/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "12093954076612099884" + "version": "0.31.34.60546", + "templateHash": "12126990142824202083" }, "name": "Application Gateway for Containers Frontend", "description": "This module deploys an Application Gateway for Containers Frontend", diff --git a/avm/res/service-networking/traffic-controller/main.bicep b/avm/res/service-networking/traffic-controller/main.bicep index 2ac083b224..13dc424458 100644 --- a/avm/res/service-networking/traffic-controller/main.bicep +++ b/avm/res/service-networking/traffic-controller/main.bicep @@ -14,20 +14,24 @@ param enableTelemetry bool = true @description('Optional. Resource tags.') param tags object? -@description('Optional. The lock settings of the service.') -param lock lockType +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.3.0' +@description('Optional. The lock settings for all Resources in the solution.') +param lock lockType? +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.3.0' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. List of Application Gateway for Containers frontends.') -param frontends frontendType +param frontends frontendType[]? +@maxLength(1) @description('Optional. List of Application Gateway for Containers associations. At this time, the number of associations is limited to 1.') -param associations associationType +param associations associationType[]? var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -208,94 +212,17 @@ output associations array = [ // Definitions // // ================ // +@export() type frontendType = { @description('Required. The name of the Application Gateway for Containers frontend.') name: string -}[]? +} -@maxLength(1) +@export() type associationType = { @description('Required. The name of the Application Gateway for Containers association.') name: string @description('Required. The resource ID of the subnet to associate with the Application Gateway for Containers.') subnetResourceId: string -}[]? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? +} diff --git a/avm/res/service-networking/traffic-controller/main.json b/avm/res/service-networking/traffic-controller/main.json index aa85cfc38c..2153d32460 100644 --- a/avm/res/service-networking/traffic-controller/main.json +++ b/avm/res/service-networking/traffic-controller/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13555357375349247834" + "version": "0.31.34.60546", + "templateHash": "1270772577226075570" }, "name": "Application Gateway for Containers", "description": "This module deploys an Application Gateway for Containers", @@ -14,41 +14,160 @@ }, "definitions": { "frontendType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the Application Gateway for Containers frontend." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Application Gateway for Containers frontend." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, "associationType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the Application Gateway for Containers association." + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Application Gateway for Containers association." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the subnet to associate with the Application Gateway for Containers." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } } }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource ID of the subnet to associate with the Application Gateway for Containers." + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true, - "maxLength": 1 + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } }, "lockType": { "type": "object", @@ -73,200 +192,87 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } }, "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -299,30 +305,48 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { - "description": "Optional. The lock settings of the service." + "description": "Optional. The lock settings for all Resources in the solution." } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } }, "frontends": { - "$ref": "#/definitions/frontendType", + "type": "array", + "items": { + "$ref": "#/definitions/frontendType" + }, + "nullable": true, "metadata": { "description": "Optional. List of Application Gateway for Containers frontends." } }, "associations": { - "$ref": "#/definitions/associationType", + "type": "array", + "items": { + "$ref": "#/definitions/associationType" + }, + "nullable": true, + "maxLength": 1, "metadata": { "description": "Optional. List of Application Gateway for Containers associations. At this time, the number of associations is limited to 1." } @@ -480,8 +504,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "12093954076612099884" + "version": "0.31.34.60546", + "templateHash": "12126990142824202083" }, "name": "Application Gateway for Containers Frontend", "description": "This module deploys an Application Gateway for Containers Frontend", @@ -586,8 +610,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "17751059838446450774" + "version": "0.31.34.60546", + "templateHash": "16237699923821445314" }, "name": "Application Gateway for Containers Association", "description": "This module deploys an Application Gateway for Containers Association", @@ -616,7 +640,7 @@ "subnetResourceId": { "type": "string", "metadata": { - "description": "Reuired. The resource ID of the subnet to associate with the traffic controller." + "description": "Required. The resource ID of the subnet to associate with the traffic controller." } } }, diff --git a/avm/res/signal-r-service/signal-r/README.md b/avm/res/signal-r-service/signal-r/README.md index 3612033f31..6d626e2528 100644 --- a/avm/res/signal-r-service/signal-r/README.md +++ b/avm/res/signal-r-service/signal-r/README.md @@ -128,6 +128,10 @@ module signalR 'br/public:avm/res/signal-r-service/signal-r:' = { kind: 'CanNotDelete' name: 'myCustomLockName' } + managedIdentities: { + systemAssigned: false + userAssignedResourceIds: '' + } networkAcls: { defaultAction: 'Allow' privateEndpoints: [ @@ -248,6 +252,12 @@ module signalR 'br/public:avm/res/signal-r-service/signal-r:' = { "name": "myCustomLockName" } }, + "managedIdentities": { + "value": { + "systemAssigned": false, + "userAssignedResourceIds": "" + } + }, "networkAcls": { "value": { "defaultAction": "Allow", @@ -362,6 +372,10 @@ param lock = { kind: 'CanNotDelete' name: 'myCustomLockName' } +param managedIdentities = { + systemAssigned: false + userAssignedResourceIds: '' +} param networkAcls = { defaultAction: 'Allow' privateEndpoints: [ @@ -702,6 +716,7 @@ param tags = { | [`liveTraceCatagoriesToEnable`](#parameter-livetracecatagoriestoenable) | array | Control permission for data plane traffic coming from public networks while private endpoint is enabled. | | [`location`](#parameter-location) | string | The location for the resource. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | | [`networkAcls`](#parameter-networkacls) | object | Networks ACLs, this value contains IPs to allow and/or Subnet information. Can only be set if the 'SKU' is not 'Free_F1'. For security reasons, it is recommended to set the DefaultAction Deny. | | [`privateEndpoints`](#parameter-privateendpoints) | array | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | | [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set. | @@ -868,6 +883,34 @@ Specify the name of lock. - Required: No - Type: string +### Parameter: `managedIdentities` + +The managed identity definition for this resource. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | + +### Parameter: `managedIdentities.systemAssigned` + +Enables system assigned managed identity on the resource. + +- Required: No +- Type: bool + +### Parameter: `managedIdentities.userAssignedResourceIds` + +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. + +- Required: No +- Type: array + ### Parameter: `networkAcls` Networks ACLs, this value contains IPs to allow and/or Subnet information. Can only be set if the 'SKU' is not 'Free_F1'. For security reasons, it is recommended to set the DefaultAction Deny. @@ -893,22 +936,22 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the Private Endpoint IP configuration is included. | | [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | -| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the Private Endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. | | [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | -| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the Private Endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | -| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS zone group to configure for the private endpoint. | +| [`name`](#parameter-privateendpointsname) | string | The name of the Private Endpoint. | +| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS Zone Group to configure for the Private Endpoint. | | [`privateLinkServiceConnectionName`](#parameter-privateendpointsprivatelinkserviceconnectionname) | string | The name of the private link connection to create. | -| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. | +| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | -| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/Resource Groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -919,7 +962,7 @@ Resource ID of the subnet where the endpoint needs to be created. ### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` -Application security groups in which the private endpoint IP configuration is included. +Application security groups in which the Private Endpoint IP configuration is included. - Required: No - Type: array @@ -935,15 +978,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -952,9 +993,16 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` -The custom name of the network interface attached to the private endpoint. +The custom name of the network interface attached to the Private Endpoint. - Required: No - Type: string @@ -968,7 +1016,7 @@ Enable/Disable usage telemetry for module. ### Parameter: `privateEndpoints.ipConfigurations` -A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. +A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. - Required: No - Type: array @@ -1032,7 +1080,7 @@ If Manual Private Link Connection is required. ### Parameter: `privateEndpoints.location` -The location to deploy the private endpoint to. +The location to deploy the Private Endpoint to. - Required: No - Type: string @@ -1082,14 +1130,14 @@ A message passed to the owner of the remote resource with the manual connection ### Parameter: `privateEndpoints.name` -The name of the private endpoint. +The name of the Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.privateDnsZoneGroup` -The private DNS zone group to configure for the private endpoint. +The private DNS Zone Group to configure for the Private Endpoint. - Required: No - Type: object @@ -1098,7 +1146,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -1108,7 +1156,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -1123,7 +1171,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -1134,7 +1182,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -1155,7 +1203,7 @@ The name of the private link connection to create. ### Parameter: `privateEndpoints.resourceGroupName` -Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. +Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. - Required: No - Type: string @@ -1176,7 +1224,7 @@ Array of role assignments to create. - `'Owner'` - `'Private DNS Zone Contributor'` - `'Reader'` - - `'Role Based Access Control Administrator (Preview)'` + - `'Role Based Access Control Administrator'` **Required parameters** @@ -1270,14 +1318,14 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". +The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.tags` -Tags to be applied on all resources/resource groups in this deployment. +Tags to be applied on all resources/Resource Groups in this deployment. - Required: No - Type: object @@ -1487,6 +1535,7 @@ Upstream templates to enable. For more information, see https://learn.microsoft. | `privateEndpoints` | array | The private endpoints of the SignalR. | | `resourceGroupName` | string | The SignalR resource group. | | `resourceId` | string | The SignalR resource ID. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | ## Cross-referenced modules @@ -1494,7 +1543,8 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.8.0` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/signal-r-service/signal-r/main.bicep b/avm/res/signal-r-service/signal-r/main.bicep index ece400d2ed..c458befb65 100644 --- a/avm/res/signal-r-service/signal-r/main.bicep +++ b/avm/res/signal-r-service/signal-r/main.bicep @@ -2,6 +2,10 @@ metadata name = 'SignalR Service SignalR' metadata description = 'This module deploys a SignalR Service SignalR.' metadata owner = 'Azure/module-maintainers' +// ============== // +// Parameters // +// ============== // + @description('Optional. The location for the resource.') param location string = resourceGroup().location @@ -98,18 +102,43 @@ param clientCertEnabled bool = false @description('Optional. Upstream templates to enable. For more information, see https://learn.microsoft.com/en-us/azure/templates/microsoft.signalrservice/2022-02-01/signalr?pivots=deployment-language-bicep#upstreamtemplate.') param upstreamTemplatesToEnable array? +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointSingleServiceType[]? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentityAllType? + +// ============= // +// Variables // +// ============= // + +var formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), + {}, + (cur, next) => union(cur, next) +) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } +var identity = !empty(managedIdentities) + ? { + type: (managedIdentities.?systemAssigned ?? false) + ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') + : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null + var liveTraceCatagories = [ for configuration in liveTraceCatagoriesToEnable: { name: configuration @@ -210,6 +239,7 @@ resource signalR 'Microsoft.SignalRService/signalR@2022-02-01' = { tier: tier } tags: tags + identity: identity properties: { cors: { allowedOrigins: allowedOrigins @@ -240,7 +270,7 @@ resource signalR 'Microsoft.SignalRService/signalR@2022-02-01' = { } } -module signalR_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.7.1' = [ +module signalR_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.8.0' = [ for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-signalR-PrivateEndpoint-${index}' scope: resourceGroup(privateEndpoint.?resourceGroupName ?? '') @@ -331,6 +361,9 @@ output resourceId string = signalR.id @description('The location the resource was deployed into.') output location string = signalR.location +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = signalR.?identity.?principalId ?? '' + @description('The private endpoints of the SignalR.') output privateEndpoints array = [ for (pe, i) in (!empty(privateEndpoints) ? array(privateEndpoints) : []): { @@ -341,128 +374,3 @@ output privateEndpoints array = [ networkInterfaceIds: signalR_privateEndpoints[i].outputs.networkInterfaceIds } ] - -// =============== // -// Definitions // -// =============== // - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') - service: string? - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? - - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? - - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? - - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? diff --git a/avm/res/signal-r-service/signal-r/main.json b/avm/res/signal-r-service/signal-r/main.json index b6f8656b92..c0ee5618de 100644 --- a/avm/res/signal-r-service/signal-r/main.json +++ b/avm/res/signal-r-service/signal-r/main.json @@ -5,331 +5,397 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "16576967735793916107" + "version": "0.30.23.60470", + "templateHash": "7411558632564019868" }, "name": "SignalR Service SignalR", "description": "This module deploys a SignalR Service SignalR.", "owner": "Azure/module-maintainers" }, "definitions": { - "lockType": { + "_1.privateEndpointCustomDnsConfigType": { "type": "object", "properties": { - "name": { + "fqdn": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Required. A list of private IP addresses of the private endpoint." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." - } - }, - "privateDnsZoneGroup": { + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." + "description": "Optional. The name of the private DNS Zone Group config." } }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, + "privateDnsZoneResourceId": { + "type": "string", "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } + "description": "Required. The resource id of the private DNS zone." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." } }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "privateEndpointSingleServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private Endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the Private Endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the Private Endpoint for. For example \"vault\" for a Key Vault Private Endpoint." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS Zone Group to configure for the Private Endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the Private Endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the Private Endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/Resource Groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like 'vault' for key vault).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -495,19 +561,28 @@ } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointSingleServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -518,6 +593,13 @@ "metadata": { "description": "Optional. Enable/Disable usage telemetry for module." } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } } }, "variables": { @@ -544,6 +626,8 @@ "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" } ], + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", @@ -593,6 +677,7 @@ "tier": "[parameters('tier')]" }, "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", "properties": { "cors": { "allowedOrigins": "[parameters('allowedOrigins')]" @@ -710,7 +795,7 @@ "_generator": { "name": "bicep", "version": "0.29.47.4906", - "templateHash": "1277254088602407590" + "templateHash": "10193943972635711937" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -1124,7 +1209,7 @@ "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" } }, "resources": { @@ -1132,7 +1217,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.8.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1444,6 +1529,13 @@ }, "value": "[reference('signalR', '2022-02-01', 'full').location]" }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('signalR', '2022-02-01', 'full'), 'identity'), 'principalId'), '')]" + }, "privateEndpoints": { "type": "array", "metadata": { diff --git a/avm/res/signal-r-service/signal-r/tests/e2e/defaults/main.test.bicep b/avm/res/signal-r-service/signal-r/tests/e2e/defaults/main.test.bicep index 8f4198f941..eb0146d99a 100644 --- a/avm/res/signal-r-service/signal-r/tests/e2e/defaults/main.test.bicep +++ b/avm/res/signal-r-service/signal-r/tests/e2e/defaults/main.test.bicep @@ -26,7 +26,7 @@ param namePrefix string = '#_namePrefix_#' // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName location: resourceLocation } diff --git a/avm/res/signal-r-service/signal-r/tests/e2e/max/dependencies.bicep b/avm/res/signal-r-service/signal-r/tests/e2e/max/dependencies.bicep index 3f02e7b5ad..f7696bde96 100644 --- a/avm/res/signal-r-service/signal-r/tests/e2e/max/dependencies.bicep +++ b/avm/res/signal-r-service/signal-r/tests/e2e/max/dependencies.bicep @@ -9,7 +9,7 @@ param managedIdentityName string var addressPrefix = '10.0.0.0/16' -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-01-01' = { name: virtualNetworkName location: location properties: { @@ -31,11 +31,11 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } } -resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2024-06-01' = { name: 'privatelink.service.signalr.net' location: 'global' - resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + resource virtualNetworkLinks 'virtualNetworkLinks@2024-06-01' = { name: '${virtualNetwork.name}-vnetlink' location: 'global' properties: { @@ -47,7 +47,7 @@ resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { } } -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { name: managedIdentityName location: location } @@ -60,3 +60,6 @@ output privateDNSZoneResourceId string = privateDNSZone.id @description('The principal ID of the created Managed Identity.') output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity') +output managedIdentityResourceId string = managedIdentity.id diff --git a/avm/res/signal-r-service/signal-r/tests/e2e/max/main.test.bicep b/avm/res/signal-r-service/signal-r/tests/e2e/max/main.test.bicep index 8ec75e7dac..55703b7f95 100644 --- a/avm/res/signal-r-service/signal-r/tests/e2e/max/main.test.bicep +++ b/avm/res/signal-r-service/signal-r/tests/e2e/max/main.test.bicep @@ -26,7 +26,7 @@ param namePrefix string = '#_namePrefix_#' // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName location: resourceLocation } @@ -53,6 +53,10 @@ module testDeployment '../../../main.bicep' = [ params: { name: '${namePrefix}-${serviceShort}-001' location: resourceLocation + managedIdentities: { + systemAssigned: false + userAssignedResourceIds: [nestedDependencies.outputs.managedIdentityResourceId] + } capacity: 2 clientCertEnabled: false disableAadAuth: false diff --git a/avm/res/signal-r-service/signal-r/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/signal-r-service/signal-r/tests/e2e/waf-aligned/dependencies.bicep index c9b4120285..4ec8f243df 100644 --- a/avm/res/signal-r-service/signal-r/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/signal-r-service/signal-r/tests/e2e/waf-aligned/dependencies.bicep @@ -28,11 +28,11 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } } -resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2024-06-01' = { name: 'privatelink.service.signalr.net' location: 'global' - resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + resource virtualNetworkLinks 'virtualNetworkLinks@2024-06-01' = { name: '${virtualNetwork.name}-vnetlink' location: 'global' properties: { diff --git a/avm/res/signal-r-service/signal-r/tests/e2e/waf-aligned/main.test.bicep b/avm/res/signal-r-service/signal-r/tests/e2e/waf-aligned/main.test.bicep index 009b496f45..6d4848011e 100644 --- a/avm/res/signal-r-service/signal-r/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/signal-r-service/signal-r/tests/e2e/waf-aligned/main.test.bicep @@ -26,7 +26,7 @@ param namePrefix string = '#_namePrefix_#' // General resources // ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { +resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: resourceGroupName location: resourceLocation } diff --git a/avm/res/signal-r-service/signal-r/version.json b/avm/res/signal-r-service/signal-r/version.json index a8eda31021..21226dd43f 100644 --- a/avm/res/signal-r-service/signal-r/version.json +++ b/avm/res/signal-r-service/signal-r/version.json @@ -1,7 +1,7 @@ { - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.5", - "pathFilters": [ - "./main.json" - ] + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.6", + "pathFilters": [ + "./main.json" + ] } \ No newline at end of file diff --git a/avm/res/signal-r-service/web-pub-sub/README.md b/avm/res/signal-r-service/web-pub-sub/README.md index c060863897..0a3a40caad 100644 --- a/avm/res/signal-r-service/web-pub-sub/README.md +++ b/avm/res/signal-r-service/web-pub-sub/README.md @@ -828,7 +828,7 @@ The managed identity definition for this resource. Only one type of identity is | Parameter | Type | Description | | :-- | :-- | :-- | | [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | ### Parameter: `managedIdentities.systemAssigned` @@ -839,7 +839,7 @@ Enables system assigned managed identity on the resource. ### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. - Required: No - Type: array @@ -868,22 +868,22 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the Private Endpoint IP configuration is included. | | [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | -| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the Private Endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. | | [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | -| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the Private Endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | -| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS zone group to configure for the private endpoint. | +| [`name`](#parameter-privateendpointsname) | string | The name of the Private Endpoint. | +| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS Zone Group to configure for the Private Endpoint. | | [`privateLinkServiceConnectionName`](#parameter-privateendpointsprivatelinkserviceconnectionname) | string | The name of the private link connection to create. | -| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. | +| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | -| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/Resource Groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -894,7 +894,7 @@ Resource ID of the subnet where the endpoint needs to be created. ### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` -Application security groups in which the private endpoint IP configuration is included. +Application security groups in which the Private Endpoint IP configuration is included. - Required: No - Type: array @@ -910,15 +910,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -927,9 +925,16 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` -The custom name of the network interface attached to the private endpoint. +The custom name of the network interface attached to the Private Endpoint. - Required: No - Type: string @@ -943,7 +948,7 @@ Enable/Disable usage telemetry for module. ### Parameter: `privateEndpoints.ipConfigurations` -A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. +A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. - Required: No - Type: array @@ -1007,7 +1012,7 @@ If Manual Private Link Connection is required. ### Parameter: `privateEndpoints.location` -The location to deploy the private endpoint to. +The location to deploy the Private Endpoint to. - Required: No - Type: string @@ -1057,14 +1062,14 @@ A message passed to the owner of the remote resource with the manual connection ### Parameter: `privateEndpoints.name` -The name of the private endpoint. +The name of the Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.privateDnsZoneGroup` -The private DNS zone group to configure for the private endpoint. +The private DNS Zone Group to configure for the Private Endpoint. - Required: No - Type: object @@ -1073,7 +1078,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -1083,7 +1088,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -1098,7 +1103,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -1109,7 +1114,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -1130,7 +1135,7 @@ The name of the private link connection to create. ### Parameter: `privateEndpoints.resourceGroupName` -Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. +Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. - Required: No - Type: string @@ -1245,14 +1250,14 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". +The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.tags` -Tags to be applied on all resources/resource groups in this deployment. +Tags to be applied on all resources/Resource Groups in this deployment. - Required: No - Type: object @@ -1447,6 +1452,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/signal-r-service/web-pub-sub/main.bicep b/avm/res/signal-r-service/web-pub-sub/main.bicep index 760511f84b..7a67928135 100644 --- a/avm/res/signal-r-service/web-pub-sub/main.bicep +++ b/avm/res/signal-r-service/web-pub-sub/main.bicep @@ -8,14 +8,17 @@ param location string = resourceGroup().location @description('Required. The name of the Web PubSub Service resource.') param name string +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointSingleServiceType[]? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the resource.') param tags object? @@ -30,8 +33,9 @@ param capacity int = 1 @description('Optional. Pricing tier of the resource.') param sku string = 'Standard_S1' +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityAllType? @description('Optional. When set as true, connection with AuthType=aad won\'t work.') param disableAadAuth bool = false @@ -305,136 +309,3 @@ output privateEndpoints array = [ networkInterfaceIds: webPubSub_privateEndpoints[i].outputs.networkInterfaceIds } ] - -// =============== // -// Definitions // -// =============== // - -type managedIdentitiesType = { - @description('Optional. Enables system assigned managed identity on the resource.') - systemAssigned: bool? - - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[]? -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') - service: string? - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? - - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? - - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? - - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? diff --git a/avm/res/signal-r-service/web-pub-sub/main.json b/avm/res/signal-r-service/web-pub-sub/main.json index 51dcc979c6..6bff47322b 100644 --- a/avm/res/signal-r-service/web-pub-sub/main.json +++ b/avm/res/signal-r-service/web-pub-sub/main.json @@ -5,36 +5,122 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17348552013839664242" + "version": "0.30.23.60470", + "templateHash": "3908904397017008201" }, "name": "SignalR Web PubSub Services", "description": "This module deploys a SignalR Web PubSub Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { + "_1.privateEndpointCustomDnsConfigType": { "type": "object", "properties": { - "systemAssigned": { - "type": "bool", + "fqdn": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, - "userAssignedResourceIds": { + "ipAddresses": { "type": "array", "items": { "type": "string" }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS Zone Group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "lockType": { "type": "object", @@ -59,300 +145,257 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." - } - }, - "privateDnsZoneGroup": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." - } - }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, - "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } + "privateEndpointSingleServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private Endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the Private Endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the Private Endpoint for. For example \"vault\" for a Key Vault Private Endpoint." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS Zone Group to configure for the Private Endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the Private Endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the Private Endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/Resource Groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like 'vault' for key vault).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -370,19 +413,28 @@ } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointSingleServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -413,7 +465,8 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." } diff --git a/avm/res/sql/server/README.md b/avm/res/sql/server/README.md index 1869610a60..5540a01906 100644 --- a/avm/res/sql/server/README.md +++ b/avm/res/sql/server/README.md @@ -25,7 +25,7 @@ This module deploys an Azure SQL Server. | `Microsoft.Sql/servers` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers) | | `Microsoft.Sql/servers/auditingSettings` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/auditingSettings) | | `Microsoft.Sql/servers/databases` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/databases) | -| `Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies) | +| `Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies` | [2023-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/2023-05-01-preview/servers/databases/backupLongTermRetentionPolicies) | | `Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies) | | `Microsoft.Sql/servers/elasticPools` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/elasticPools) | | `Microsoft.Sql/servers/encryptionProtector` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/encryptionProtector) | @@ -46,11 +46,12 @@ The following section provides usage examples for the module, which were used to - [With an administrator](#example-1-with-an-administrator) - [With audit settings](#example-2-with-audit-settings) - [Using only defaults](#example-3-using-only-defaults) -- [Deploying with a key vault reference to save secrets](#example-4-deploying-with-a-key-vault-reference-to-save-secrets) -- [Using large parameter set](#example-5-using-large-parameter-set) -- [With a secondary database](#example-6-with-a-secondary-database) -- [With vulnerability assessment](#example-7-with-vulnerability-assessment) -- [WAF-aligned](#example-8-waf-aligned) +- [Using elastic pool](#example-4-using-elastic-pool) +- [Deploying with a key vault reference to save secrets](#example-5-deploying-with-a-key-vault-reference-to-save-secrets) +- [Using large parameter set](#example-6-using-large-parameter-set) +- [With a secondary database](#example-7-with-a-secondary-database) +- [With vulnerability assessment](#example-8-with-vulnerability-assessment) +- [WAF-aligned](#example-9-waf-aligned) ### Example 1: _With an administrator_ @@ -312,7 +313,134 @@ param location = ''

    -### Example 4: _Deploying with a key vault reference to save secrets_ +### Example 4: _Using elastic pool_ + +This instance deploys the module with an elastic pool. + + +

    + +via Bicep module + +```bicep +module server 'br/public:avm/res/sql/server:' = { + name: 'serverDeployment' + params: { + // Required parameters + name: 'ssep001' + // Non-required parameters + administratorLogin: 'adminUserName' + administratorLoginPassword: '' + elasticPools: [ + { + name: 'ssep-ep-001' + } + { + name: 'ssep-ep-002' + perDatabaseSettings: { + maxCapacity: '4' + minCapacity: '0.5' + } + sku: { + capacity: 4 + name: 'GP_Gen5' + tier: 'GeneralPurpose' + } + } + ] + location: '' + } +} +``` + +
    +

    + +

    + +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "ssep001" + }, + // Non-required parameters + "administratorLogin": { + "value": "adminUserName" + }, + "administratorLoginPassword": { + "value": "" + }, + "elasticPools": { + "value": [ + { + "name": "ssep-ep-001" + }, + { + "name": "ssep-ep-002", + "perDatabaseSettings": { + "maxCapacity": "4", + "minCapacity": "0.5" + }, + "sku": { + "capacity": 4, + "name": "GP_Gen5", + "tier": "GeneralPurpose" + } + } + ] + }, + "location": { + "value": "" + } + } +} +``` + +
    +

    + +

    + +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/sql/server:' + +// Required parameters +param name = 'ssep001' +// Non-required parameters +param administratorLogin = 'adminUserName' +param administratorLoginPassword = '' +param elasticPools = [ + { + name: 'ssep-ep-001' + } + { + name: 'ssep-ep-002' + perDatabaseSettings: { + maxCapacity: '4' + minCapacity: '0.5' + } + sku: { + capacity: 4 + name: 'GP_Gen5' + tier: 'GeneralPurpose' + } + } +] +param location = '' +``` + +
    +

    + +### Example 5: _Deploying with a key vault reference to save secrets_ This instance deploys the module saving all its secrets in a key vault. @@ -420,7 +548,7 @@ param secretsExportConfiguration = {

    -### Example 5: _Using large parameter set_ +### Example 6: _Using large parameter set_ This instance deploys the module with most of its features enabled. @@ -456,27 +584,31 @@ module server 'br/public:avm/res/sql/server:' = { workspaceResourceId: '' } ] - elasticPoolId: '' - encryptionProtectorObj: { - serverKeyName: '' - serverKeyType: 'AzureKeyVault' - } + elasticPoolResourceId: '' licenseType: 'LicenseIncluded' maxSizeBytes: 34359738368 name: 'sqlsmaxdb-001' - skuCapacity: 0 - skuName: 'ElasticPool' - skuTier: 'GeneralPurpose' + sku: { + capacity: 0 + name: 'ElasticPool' + tier: 'GeneralPurpose' + } } ] elasticPools: [ { name: 'sqlsmax-ep-001' - skuCapacity: 10 - skuName: 'GP_Gen5' - skuTier: 'GeneralPurpose' + sku: { + capacity: 10 + name: 'GP_Gen5' + tier: 'GeneralPurpose' + } } ] + encryptionProtectorObj: { + serverKeyName: '' + serverKeyType: 'AzureKeyVault' + } firewallRules: [ { endIpAddress: '0.0.0.0' @@ -623,17 +755,15 @@ module server 'br/public:avm/res/sql/server:' = { "workspaceResourceId": "" } ], - "elasticPoolId": "", - "encryptionProtectorObj": { - "serverKeyName": "", - "serverKeyType": "AzureKeyVault" - }, + "elasticPoolResourceId": "", "licenseType": "LicenseIncluded", "maxSizeBytes": 34359738368, "name": "sqlsmaxdb-001", - "skuCapacity": 0, - "skuName": "ElasticPool", - "skuTier": "GeneralPurpose" + "sku": { + "capacity": 0, + "name": "ElasticPool", + "tier": "GeneralPurpose" + } } ] }, @@ -641,12 +771,20 @@ module server 'br/public:avm/res/sql/server:' = { "value": [ { "name": "sqlsmax-ep-001", - "skuCapacity": 10, - "skuName": "GP_Gen5", - "skuTier": "GeneralPurpose" + "sku": { + "capacity": 10, + "name": "GP_Gen5", + "tier": "GeneralPurpose" + } } ] }, + "encryptionProtectorObj": { + "value": { + "serverKeyName": "", + "serverKeyType": "AzureKeyVault" + } + }, "firewallRules": { "value": [ { @@ -812,27 +950,31 @@ param databases = [ workspaceResourceId: '' } ] - elasticPoolId: '' - encryptionProtectorObj: { - serverKeyName: '' - serverKeyType: 'AzureKeyVault' - } + elasticPoolResourceId: '' licenseType: 'LicenseIncluded' maxSizeBytes: 34359738368 name: 'sqlsmaxdb-001' - skuCapacity: 0 - skuName: 'ElasticPool' - skuTier: 'GeneralPurpose' + sku: { + capacity: 0 + name: 'ElasticPool' + tier: 'GeneralPurpose' + } } ] param elasticPools = [ { name: 'sqlsmax-ep-001' - skuCapacity: 10 - skuName: 'GP_Gen5' - skuTier: 'GeneralPurpose' + sku: { + capacity: 10 + name: 'GP_Gen5' + tier: 'GeneralPurpose' + } } ] +param encryptionProtectorObj = { + serverKeyName: '' + serverKeyType: 'AzureKeyVault' +} param firewallRules = [ { endIpAddress: '0.0.0.0' @@ -940,7 +1082,7 @@ param vulnerabilityAssessmentsObj = {

    -### Example 6: _With a secondary database_ +### Example 7: _With a secondary database_ This instance deploys the module with a secondary database. @@ -963,8 +1105,10 @@ module server 'br/public:avm/res/sql/server:' = { createMode: 'Secondary' maxSizeBytes: 2147483648 name: '' - skuName: 'Basic' - skuTier: 'Basic' + sku: { + name: 'Basic' + tier: 'Basic' + } sourceDatabaseResourceId: '' } ] @@ -1007,8 +1151,10 @@ module server 'br/public:avm/res/sql/server:' = { "createMode": "Secondary", "maxSizeBytes": 2147483648, "name": "", - "skuName": "Basic", - "skuTier": "Basic", + "sku": { + "name": "Basic", + "tier": "Basic" + }, "sourceDatabaseResourceId": "" } ] @@ -1047,8 +1193,10 @@ param databases = [ createMode: 'Secondary' maxSizeBytes: 2147483648 name: '' - skuName: 'Basic' - skuTier: 'Basic' + sku: { + name: 'Basic' + tier: 'Basic' + } sourceDatabaseResourceId: '' } ] @@ -1063,7 +1211,7 @@ param tags = {

    -### Example 7: _With vulnerability assessment_ +### Example 8: _With vulnerability assessment_ This instance deploys the module with a vulnerability assessment. @@ -1240,7 +1388,7 @@ param vulnerabilityAssessmentsObj = {

    -### Example 8: _WAF-aligned_ +### Example 9: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. @@ -1281,28 +1429,32 @@ module server 'br/public:avm/res/sql/server:' = { workspaceResourceId: '' } ] - elasticPoolId: '' - encryptionProtectorObj: { - serverKeyName: '' - serverKeyType: 'AzureKeyVault' - } + elasticPoolResourceId: '' licenseType: 'LicenseIncluded' maxSizeBytes: 34359738368 name: 'sqlswafdb-001' - skuCapacity: 0 - skuName: 'ElasticPool' - skuTier: 'GeneralPurpose' + sku: { + capacity: 0 + name: 'ElasticPool' + tier: 'GeneralPurpose' + } } ] elasticPools: [ { maintenanceConfigurationId: '' name: 'sqlswaf-ep-001' - skuCapacity: 10 - skuName: 'GP_Gen5' - skuTier: 'GeneralPurpose' + sku: { + capacity: 10 + name: 'GP_Gen5' + tier: 'GeneralPurpose' + } } ] + encryptionProtectorObj: { + serverKeyName: '' + serverKeyType: 'AzureKeyVault' + } keys: [ { serverKeyType: 'AzureKeyVault' @@ -1412,17 +1564,15 @@ module server 'br/public:avm/res/sql/server:' = { "workspaceResourceId": "" } ], - "elasticPoolId": "", - "encryptionProtectorObj": { - "serverKeyName": "", - "serverKeyType": "AzureKeyVault" - }, + "elasticPoolResourceId": "", "licenseType": "LicenseIncluded", "maxSizeBytes": 34359738368, "name": "sqlswafdb-001", - "skuCapacity": 0, - "skuName": "ElasticPool", - "skuTier": "GeneralPurpose" + "sku": { + "capacity": 0, + "name": "ElasticPool", + "tier": "GeneralPurpose" + } } ] }, @@ -1431,12 +1581,20 @@ module server 'br/public:avm/res/sql/server:' = { { "maintenanceConfigurationId": "", "name": "sqlswaf-ep-001", - "skuCapacity": 10, - "skuName": "GP_Gen5", - "skuTier": "GeneralPurpose" + "sku": { + "capacity": 10, + "name": "GP_Gen5", + "tier": "GeneralPurpose" + } } ] }, + "encryptionProtectorObj": { + "value": { + "serverKeyName": "", + "serverKeyType": "AzureKeyVault" + } + }, "keys": { "value": [ { @@ -1561,28 +1719,32 @@ param databases = [ workspaceResourceId: '' } ] - elasticPoolId: '' - encryptionProtectorObj: { - serverKeyName: '' - serverKeyType: 'AzureKeyVault' - } + elasticPoolResourceId: '' licenseType: 'LicenseIncluded' maxSizeBytes: 34359738368 name: 'sqlswafdb-001' - skuCapacity: 0 - skuName: 'ElasticPool' - skuTier: 'GeneralPurpose' + sku: { + capacity: 0 + name: 'ElasticPool' + tier: 'GeneralPurpose' + } } ] param elasticPools = [ { maintenanceConfigurationId: '' name: 'sqlswaf-ep-001' - skuCapacity: 10 - skuName: 'GP_Gen5' - skuTier: 'GeneralPurpose' + sku: { + capacity: 10 + name: 'GP_Gen5' + tier: 'GeneralPurpose' + } } ] +param encryptionProtectorObj = { + serverKeyName: '' + serverKeyType: 'AzureKeyVault' +} param keys = [ { serverKeyType: 'AzureKeyVault' @@ -1676,8 +1838,10 @@ param vulnerabilityAssessmentsObj = { | [`elasticPools`](#parameter-elasticpools) | array | The Elastic Pools to create in the server. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`encryptionProtectorObj`](#parameter-encryptionprotectorobj) | object | The encryption protection configuration. | +| [`federatedClientId`](#parameter-federatedclientid) | string | The Client id used for cross tenant CMK scenario. | | [`firewallRules`](#parameter-firewallrules) | array | The firewall rules to create in the server. | | [`isIPv6Enabled`](#parameter-isipv6enabled) | string | Whether or not to enable IPv6 support for this server. | +| [`keyId`](#parameter-keyid) | string | A CMK URI of the key to use for encryption. | | [`keys`](#parameter-keys) | array | The keys to configure. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | @@ -1722,7 +1886,78 @@ The Azure Active Directory (AAD) administrator authentication. Required if no `a - Required: No - Type: object -- Default: `{}` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`azureADOnlyAuthentication`](#parameter-administratorsazureadonlyauthentication) | bool | Azure Active Directory only Authentication enabled. | +| [`login`](#parameter-administratorslogin) | string | Login name of the server administrator. | +| [`principalType`](#parameter-administratorsprincipaltype) | string | Principal Type of the sever administrator. | +| [`sid`](#parameter-administratorssid) | string | SID (object ID) of the server administrator. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`administratorType`](#parameter-administratorsadministratortype) | string | Type of the sever administrator. | +| [`tenantId`](#parameter-administratorstenantid) | string | Tenant ID of the administrator. | + +### Parameter: `administrators.azureADOnlyAuthentication` + +Azure Active Directory only Authentication enabled. + +- Required: Yes +- Type: bool + +### Parameter: `administrators.login` + +Login name of the server administrator. + +- Required: Yes +- Type: string + +### Parameter: `administrators.principalType` + +Principal Type of the sever administrator. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Application' + 'Group' + 'User' + ] + ``` + +### Parameter: `administrators.sid` + +SID (object ID) of the server administrator. + +- Required: Yes +- Type: string + +### Parameter: `administrators.administratorType` + +Type of the sever administrator. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'ActiveDirectory' + ] + ``` + +### Parameter: `administrators.tenantId` + +Tenant ID of the administrator. + +- Required: No +- Type: string ### Parameter: `primaryUserAssignedIdentityId` @@ -1738,12 +1973,7 @@ The audit settings configuration. - Required: No - Type: object - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`state`](#parameter-auditsettingsstate) | string | Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required. | +- Default: `{}` **Optional parameters** @@ -1757,22 +1987,9 @@ The audit settings configuration. | [`name`](#parameter-auditsettingsname) | string | Specifies the name of the audit settings. | | [`queueDelayMs`](#parameter-auditsettingsqueuedelayms) | int | Specifies the amount of time in milliseconds that can elapse before audit actions are forced to be processed. | | [`retentionDays`](#parameter-auditsettingsretentiondays) | int | Specifies the number of days to keep in the audit logs in the storage account. | +| [`state`](#parameter-auditsettingsstate) | string | Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required. | | [`storageAccountResourceId`](#parameter-auditsettingsstorageaccountresourceid) | string | Specifies the identifier key of the auditing storage account. | -### Parameter: `auditSettings.state` - -Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required. - -- Required: Yes -- Type: string -- Allowed: - ```Bicep - [ - 'Disabled' - 'Enabled' - ] - ``` - ### Parameter: `auditSettings.auditActionsAndGroups` Specifies the Actions-Groups and Actions to audit. @@ -1829,6 +2046,20 @@ Specifies the number of days to keep in the audit logs in the storage account. - Required: No - Type: int +### Parameter: `auditSettings.state` + +Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + ### Parameter: `auditSettings.storageAccountResourceId` Specifies the identifier key of the auditing storage account. @@ -1844,38 +2075,944 @@ The databases to create in the server. - Type: array - Default: `[]` -### Parameter: `elasticPools` - -The Elastic Pools to create in the server. +**Required parameters** -- Required: No -- Type: array -- Default: `[]` +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-databasesname) | string | The name of the Elastic Pool. | -### Parameter: `enableTelemetry` +**Optional parameters** -Enable/Disable usage telemetry for module. +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoPauseDelay`](#parameter-databasesautopausedelay) | int | Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled. | +| [`availabilityZone`](#parameter-databasesavailabilityzone) | string | Specifies the availability zone the database is pinned to. | +| [`backupLongTermRetentionPolicy`](#parameter-databasesbackuplongtermretentionpolicy) | object | The long term backup retention policy for the database. | +| [`backupShortTermRetentionPolicy`](#parameter-databasesbackupshorttermretentionpolicy) | object | The short term backup retention policy for the database. | +| [`catalogCollation`](#parameter-databasescatalogcollation) | string | Collation of the metadata catalog. | +| [`collation`](#parameter-databasescollation) | string | The collation of the database. | +| [`createMode`](#parameter-databasescreatemode) | string | Specifies the mode of database creation. | +| [`diagnosticSettings`](#parameter-databasesdiagnosticsettings) | array | The diagnostic settings of the service. | +| [`elasticPoolResourceId`](#parameter-databaseselasticpoolresourceid) | string | The resource identifier of the elastic pool containing this database. | +| [`encryptionProtector`](#parameter-databasesencryptionprotector) | string | The azure key vault URI of the database if it's configured with per Database Customer Managed Keys. | +| [`encryptionProtectorAutoRotation`](#parameter-databasesencryptionprotectorautorotation) | bool | The flag to enable or disable auto rotation of database encryption protector AKV key. | +| [`federatedClientId`](#parameter-databasesfederatedclientid) | string | The Client id used for cross tenant per database CMK scenario. | +| [`freeLimitExhaustionBehavior`](#parameter-databasesfreelimitexhaustionbehavior) | string | Specifies the behavior when monthly free limits are exhausted for the free database. | +| [`highAvailabilityReplicaCount`](#parameter-databaseshighavailabilityreplicacount) | int | The number of secondary replicas associated with the database that are used to provide high availability. Not applicable to a Hyperscale database within an elastic pool. | +| [`isLedgerOn`](#parameter-databasesisledgeron) | bool | Whether or not this database is a ledger database, which means all tables in the database are ledger tables. | +| [`licenseType`](#parameter-databaseslicensetype) | string | The license type to apply for this database. | +| [`longTermRetentionBackupResourceId`](#parameter-databaseslongtermretentionbackupresourceid) | string | The resource identifier of the long term retention backup associated with create operation of this database. | +| [`maintenanceConfigurationId`](#parameter-databasesmaintenanceconfigurationid) | string | Maintenance configuration id assigned to the database. This configuration defines the period when the maintenance updates will occur. | +| [`manualCutover`](#parameter-databasesmanualcutover) | bool | Whether or not customer controlled manual cutover needs to be done during Update Database operation to Hyperscale tier. | +| [`maxSizeBytes`](#parameter-databasesmaxsizebytes) | int | The max size of the database expressed in bytes. | +| [`minCapacity`](#parameter-databasesmincapacity) | string | Minimal capacity that database will always have allocated, if not paused. | +| [`performCutover`](#parameter-databasesperformcutover) | bool | To trigger customer controlled manual cutover during the wait state while Scaling operation is in progress. | +| [`preferredEnclaveType`](#parameter-databasespreferredenclavetype) | string | Type of enclave requested on the database. | +| [`readScale`](#parameter-databasesreadscale) | string | The state of read-only routing. If enabled, connections that have application intent set to readonly in their connection string may be routed to a readonly secondary replica in the same region. Not applicable to a Hyperscale database within an elastic pool. | +| [`recoverableDatabaseResourceId`](#parameter-databasesrecoverabledatabaseresourceid) | string | The resource identifier of the recoverable database associated with create operation of this database. | +| [`recoveryServicesRecoveryPointResourceId`](#parameter-databasesrecoveryservicesrecoverypointresourceid) | string | The resource identifier of the recovery point associated with create operation of this database. | +| [`requestedBackupStorageRedundancy`](#parameter-databasesrequestedbackupstorageredundancy) | string | The storage account type to be used to store backups for this database. | +| [`restorableDroppedDatabaseResourceId`](#parameter-databasesrestorabledroppeddatabaseresourceid) | string | The resource identifier of the restorable dropped database associated with create operation of this database. | +| [`restorePointInTime`](#parameter-databasesrestorepointintime) | string | Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database. | +| [`sampleName`](#parameter-databasessamplename) | string | The name of the sample schema to apply when creating this database. | +| [`secondaryType`](#parameter-databasessecondarytype) | string | The secondary type of the database if it is a secondary. | +| [`sku`](#parameter-databasessku) | object | The database SKU. | +| [`sourceDatabaseDeletionDate`](#parameter-databasessourcedatabasedeletiondate) | string | Specifies the time that the database was deleted. | +| [`sourceDatabaseResourceId`](#parameter-databasessourcedatabaseresourceid) | string | The resource identifier of the source database associated with create operation of this database. | +| [`sourceResourceId`](#parameter-databasessourceresourceid) | string | The resource identifier of the source associated with the create operation of this database. | +| [`tags`](#parameter-databasestags) | object | Tags of the resource. | +| [`useFreeLimit`](#parameter-databasesusefreelimit) | bool | Whether or not the database uses free monthly limits. Allowed on one database in a subscription. | +| [`zoneRedundant`](#parameter-databaseszoneredundant) | bool | Whether or not this database is zone redundant, which means the replicas of this database will be spread across multiple availability zones. | + +### Parameter: `databases.name` + +The name of the Elastic Pool. -- Required: No -- Type: bool -- Default: `True` +- Required: Yes +- Type: string -### Parameter: `encryptionProtectorObj` +### Parameter: `databases.autoPauseDelay` -The encryption protection configuration. +Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled. - Required: No -- Type: object -- Default: `{}` +- Type: int -### Parameter: `firewallRules` +### Parameter: `databases.availabilityZone` -The firewall rules to create in the server. +Specifies the availability zone the database is pinned to. - Required: No -- Type: array -- Default: `[]` - +- Type: string +- Allowed: + ```Bicep + [ + '1' + '2' + '3' + 'NoPreference' + ] + ``` + +### Parameter: `databases.backupLongTermRetentionPolicy` + +The long term backup retention policy for the database. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`backupStorageAccessTier`](#parameter-databasesbackuplongtermretentionpolicybackupstorageaccesstier) | string | The BackupStorageAccessTier for the LTR backups. | +| [`makeBackupsImmutable`](#parameter-databasesbackuplongtermretentionpolicymakebackupsimmutable) | bool | The setting whether to make LTR backups immutable. | +| [`monthlyRetention`](#parameter-databasesbackuplongtermretentionpolicymonthlyretention) | string | Monthly retention in ISO 8601 duration format. | +| [`weeklyRetention`](#parameter-databasesbackuplongtermretentionpolicyweeklyretention) | string | Weekly retention in ISO 8601 duration format. | +| [`weekOfYear`](#parameter-databasesbackuplongtermretentionpolicyweekofyear) | int | Week of year backup to keep for yearly retention. | +| [`yearlyRetention`](#parameter-databasesbackuplongtermretentionpolicyyearlyretention) | string | Yearly retention in ISO 8601 duration format. | + +### Parameter: `databases.backupLongTermRetentionPolicy.backupStorageAccessTier` + +The BackupStorageAccessTier for the LTR backups. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Archive' + 'Hot' + ] + ``` + +### Parameter: `databases.backupLongTermRetentionPolicy.makeBackupsImmutable` + +The setting whether to make LTR backups immutable. + +- Required: No +- Type: bool + +### Parameter: `databases.backupLongTermRetentionPolicy.monthlyRetention` + +Monthly retention in ISO 8601 duration format. + +- Required: No +- Type: string + +### Parameter: `databases.backupLongTermRetentionPolicy.weeklyRetention` + +Weekly retention in ISO 8601 duration format. + +- Required: No +- Type: string + +### Parameter: `databases.backupLongTermRetentionPolicy.weekOfYear` + +Week of year backup to keep for yearly retention. + +- Required: No +- Type: int + +### Parameter: `databases.backupLongTermRetentionPolicy.yearlyRetention` + +Yearly retention in ISO 8601 duration format. + +- Required: No +- Type: string + +### Parameter: `databases.backupShortTermRetentionPolicy` + +The short term backup retention policy for the database. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`diffBackupIntervalInHours`](#parameter-databasesbackupshorttermretentionpolicydiffbackupintervalinhours) | int | Differential backup interval in hours. For Hyperscale tiers this value will be ignored. | +| [`retentionDays`](#parameter-databasesbackupshorttermretentionpolicyretentiondays) | int | Point-in-time retention in days. | + +### Parameter: `databases.backupShortTermRetentionPolicy.diffBackupIntervalInHours` + +Differential backup interval in hours. For Hyperscale tiers this value will be ignored. + +- Required: No +- Type: int + +### Parameter: `databases.backupShortTermRetentionPolicy.retentionDays` + +Point-in-time retention in days. + +- Required: No +- Type: int + +### Parameter: `databases.catalogCollation` + +Collation of the metadata catalog. + +- Required: No +- Type: string + +### Parameter: `databases.collation` + +The collation of the database. + +- Required: No +- Type: string + +### Parameter: `databases.createMode` + +Specifies the mode of database creation. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Copy' + 'Default' + 'OnlineSecondary' + 'PointInTimeRestore' + 'Recovery' + 'Restore' + 'RestoreExternalBackup' + 'RestoreExternalBackupSecondary' + 'RestoreLongTermRetentionBackup' + 'Secondary' + ] + ``` + +### Parameter: `databases.diagnosticSettings` + +The diagnostic settings of the service. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`eventHubAuthorizationRuleResourceId`](#parameter-databasesdiagnosticsettingseventhubauthorizationruleresourceid) | 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. | +| [`eventHubName`](#parameter-databasesdiagnosticsettingseventhubname) | 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. | +| [`logAnalyticsDestinationType`](#parameter-databasesdiagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | +| [`logCategoriesAndGroups`](#parameter-databasesdiagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | +| [`marketplacePartnerResourceId`](#parameter-databasesdiagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | +| [`metricCategories`](#parameter-databasesdiagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | +| [`name`](#parameter-databasesdiagnosticsettingsname) | string | The name of the diagnostic setting. | +| [`storageAccountResourceId`](#parameter-databasesdiagnosticsettingsstorageaccountresourceid) | 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. | +| [`workspaceResourceId`](#parameter-databasesdiagnosticsettingsworkspaceresourceid) | 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. | + +### Parameter: `databases.diagnosticSettings.eventHubAuthorizationRuleResourceId` + +Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. + +- Required: No +- Type: string + +### Parameter: `databases.diagnosticSettings.eventHubName` + +Name 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. + +- Required: No +- Type: string + +### Parameter: `databases.diagnosticSettings.logAnalyticsDestinationType` + +A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzureDiagnostics' + 'Dedicated' + ] + ``` + +### Parameter: `databases.diagnosticSettings.logCategoriesAndGroups` + +The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`category`](#parameter-databasesdiagnosticsettingslogcategoriesandgroupscategory) | string | Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here. | +| [`categoryGroup`](#parameter-databasesdiagnosticsettingslogcategoriesandgroupscategorygroup) | string | Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs. | +| [`enabled`](#parameter-databasesdiagnosticsettingslogcategoriesandgroupsenabled) | bool | Enable or disable the category explicitly. Default is `true`. | + +### Parameter: `databases.diagnosticSettings.logCategoriesAndGroups.category` + +Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here. + +- Required: No +- Type: string + +### Parameter: `databases.diagnosticSettings.logCategoriesAndGroups.categoryGroup` + +Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs. + +- Required: No +- Type: string + +### Parameter: `databases.diagnosticSettings.logCategoriesAndGroups.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + +### Parameter: `databases.diagnosticSettings.marketplacePartnerResourceId` + +The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. + +- Required: No +- Type: string + +### Parameter: `databases.diagnosticSettings.metricCategories` + +The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`category`](#parameter-databasesdiagnosticsettingsmetriccategoriescategory) | string | Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enabled`](#parameter-databasesdiagnosticsettingsmetriccategoriesenabled) | bool | Enable or disable the category explicitly. Default is `true`. | + +### Parameter: `databases.diagnosticSettings.metricCategories.category` + +Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics. + +- Required: Yes +- Type: string + +### Parameter: `databases.diagnosticSettings.metricCategories.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + +### Parameter: `databases.diagnosticSettings.name` + +The name of the diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `databases.diagnosticSettings.storageAccountResourceId` + +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. + +- Required: No +- Type: string + +### Parameter: `databases.diagnosticSettings.workspaceResourceId` + +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. + +- Required: No +- Type: string + +### Parameter: `databases.elasticPoolResourceId` + +The resource identifier of the elastic pool containing this database. + +- Required: No +- Type: string + +### Parameter: `databases.encryptionProtector` + +The azure key vault URI of the database if it's configured with per Database Customer Managed Keys. + +- Required: No +- Type: string + +### Parameter: `databases.encryptionProtectorAutoRotation` + +The flag to enable or disable auto rotation of database encryption protector AKV key. + +- Required: No +- Type: bool + +### Parameter: `databases.federatedClientId` + +The Client id used for cross tenant per database CMK scenario. + +- Required: No +- Type: string + +### Parameter: `databases.freeLimitExhaustionBehavior` + +Specifies the behavior when monthly free limits are exhausted for the free database. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AutoPause' + 'BillOverUsage' + ] + ``` + +### Parameter: `databases.highAvailabilityReplicaCount` + +The number of secondary replicas associated with the database that are used to provide high availability. Not applicable to a Hyperscale database within an elastic pool. + +- Required: No +- Type: int + +### Parameter: `databases.isLedgerOn` + +Whether or not this database is a ledger database, which means all tables in the database are ledger tables. + +- Required: No +- Type: bool + +### Parameter: `databases.licenseType` + +The license type to apply for this database. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'BasePrice' + 'LicenseIncluded' + ] + ``` + +### Parameter: `databases.longTermRetentionBackupResourceId` + +The resource identifier of the long term retention backup associated with create operation of this database. + +- Required: No +- Type: string + +### Parameter: `databases.maintenanceConfigurationId` + +Maintenance configuration id assigned to the database. This configuration defines the period when the maintenance updates will occur. + +- Required: No +- Type: string + +### Parameter: `databases.manualCutover` + +Whether or not customer controlled manual cutover needs to be done during Update Database operation to Hyperscale tier. + +- Required: No +- Type: bool + +### Parameter: `databases.maxSizeBytes` + +The max size of the database expressed in bytes. + +- Required: No +- Type: int + +### Parameter: `databases.minCapacity` + +Minimal capacity that database will always have allocated, if not paused. + +- Required: No +- Type: string + +### Parameter: `databases.performCutover` + +To trigger customer controlled manual cutover during the wait state while Scaling operation is in progress. + +- Required: No +- Type: bool + +### Parameter: `databases.preferredEnclaveType` + +Type of enclave requested on the database. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Default' + 'VBS' + ] + ``` + +### Parameter: `databases.readScale` + +The state of read-only routing. If enabled, connections that have application intent set to readonly in their connection string may be routed to a readonly secondary replica in the same region. Not applicable to a Hyperscale database within an elastic pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `databases.recoverableDatabaseResourceId` + +The resource identifier of the recoverable database associated with create operation of this database. + +- Required: No +- Type: string + +### Parameter: `databases.recoveryServicesRecoveryPointResourceId` + +The resource identifier of the recovery point associated with create operation of this database. + +- Required: No +- Type: string + +### Parameter: `databases.requestedBackupStorageRedundancy` + +The storage account type to be used to store backups for this database. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Geo' + 'GeoZone' + 'Local' + 'Zone' + ] + ``` + +### Parameter: `databases.restorableDroppedDatabaseResourceId` + +The resource identifier of the restorable dropped database associated with create operation of this database. + +- Required: No +- Type: string + +### Parameter: `databases.restorePointInTime` + +Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database. + +- Required: No +- Type: string + +### Parameter: `databases.sampleName` + +The name of the sample schema to apply when creating this database. + +- Required: No +- Type: string + +### Parameter: `databases.secondaryType` + +The secondary type of the database if it is a secondary. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Geo' + 'Named' + 'Standby' + ] + ``` + +### Parameter: `databases.sku` + +The database SKU. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-databasesskuname) | string | The name of the SKU, typically, a letter + Number code, e.g. P3. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacity`](#parameter-databasesskucapacity) | int | The capacity of the particular SKU. | +| [`family`](#parameter-databasesskufamily) | string | If the service has different generations of hardware, for the same SKU, then that can be captured here. | +| [`size`](#parameter-databasesskusize) | string | Size of the particular SKU. | +| [`tier`](#parameter-databasesskutier) | string | The tier or edition of the particular SKU, e.g. Basic, Premium. | + +### Parameter: `databases.sku.name` + +The name of the SKU, typically, a letter + Number code, e.g. P3. + +- Required: Yes +- Type: string + +### Parameter: `databases.sku.capacity` + +The capacity of the particular SKU. + +- Required: No +- Type: int + +### Parameter: `databases.sku.family` + +If the service has different generations of hardware, for the same SKU, then that can be captured here. + +- Required: No +- Type: string + +### Parameter: `databases.sku.size` + +Size of the particular SKU. + +- Required: No +- Type: string + +### Parameter: `databases.sku.tier` + +The tier or edition of the particular SKU, e.g. Basic, Premium. + +- Required: No +- Type: string + +### Parameter: `databases.sourceDatabaseDeletionDate` + +Specifies the time that the database was deleted. + +- Required: No +- Type: string + +### Parameter: `databases.sourceDatabaseResourceId` + +The resource identifier of the source database associated with create operation of this database. + +- Required: No +- Type: string + +### Parameter: `databases.sourceResourceId` + +The resource identifier of the source associated with the create operation of this database. + +- Required: No +- Type: string + +### Parameter: `databases.tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `databases.useFreeLimit` + +Whether or not the database uses free monthly limits. Allowed on one database in a subscription. + +- Required: No +- Type: bool + +### Parameter: `databases.zoneRedundant` + +Whether or not this database is zone redundant, which means the replicas of this database will be spread across multiple availability zones. + +- Required: No +- Type: bool + +### Parameter: `elasticPools` + +The Elastic Pools to create in the server. + +- Required: No +- Type: array +- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-elasticpoolsname) | string | The name of the Elastic Pool. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoPauseDelay`](#parameter-elasticpoolsautopausedelay) | int | Time in minutes after which elastic pool is automatically paused. A value of -1 means that automatic pause is disabled. | +| [`availabilityZone`](#parameter-elasticpoolsavailabilityzone) | string | Specifies the availability zone the pool's primary replica is pinned to. | +| [`highAvailabilityReplicaCount`](#parameter-elasticpoolshighavailabilityreplicacount) | int | The number of secondary replicas associated with the elastic pool that are used to provide high availability. Applicable only to Hyperscale elastic pools. | +| [`licenseType`](#parameter-elasticpoolslicensetype) | string | The license type to apply for this elastic pool. | +| [`maintenanceConfigurationId`](#parameter-elasticpoolsmaintenanceconfigurationid) | string | Maintenance configuration id assigned to the elastic pool. This configuration defines the period when the maintenance updates will will occur. | +| [`maxSizeBytes`](#parameter-elasticpoolsmaxsizebytes) | int | The storage limit for the database elastic pool in bytes. | +| [`minCapacity`](#parameter-elasticpoolsmincapacity) | int | Minimal capacity that serverless pool will not shrink below, if not paused. | +| [`perDatabaseSettings`](#parameter-elasticpoolsperdatabasesettings) | object | The per database settings for the elastic pool. | +| [`preferredEnclaveType`](#parameter-elasticpoolspreferredenclavetype) | string | Type of enclave requested on the elastic pool. | +| [`sku`](#parameter-elasticpoolssku) | object | The elastic pool SKU. | +| [`tags`](#parameter-elasticpoolstags) | object | Tags of the resource. | +| [`zoneRedundant`](#parameter-elasticpoolszoneredundant) | bool | Whether or not this elastic pool is zone redundant, which means the replicas of this elastic pool will be spread across multiple availability zones. | + +### Parameter: `elasticPools.name` + +The name of the Elastic Pool. + +- Required: Yes +- Type: string + +### Parameter: `elasticPools.autoPauseDelay` + +Time in minutes after which elastic pool is automatically paused. A value of -1 means that automatic pause is disabled. + +- Required: No +- Type: int + +### Parameter: `elasticPools.availabilityZone` + +Specifies the availability zone the pool's primary replica is pinned to. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '1' + '2' + '3' + 'NoPreference' + ] + ``` + +### Parameter: `elasticPools.highAvailabilityReplicaCount` + +The number of secondary replicas associated with the elastic pool that are used to provide high availability. Applicable only to Hyperscale elastic pools. + +- Required: No +- Type: int + +### Parameter: `elasticPools.licenseType` + +The license type to apply for this elastic pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'BasePrice' + 'LicenseIncluded' + ] + ``` + +### Parameter: `elasticPools.maintenanceConfigurationId` + +Maintenance configuration id assigned to the elastic pool. This configuration defines the period when the maintenance updates will will occur. + +- Required: No +- Type: string + +### Parameter: `elasticPools.maxSizeBytes` + +The storage limit for the database elastic pool in bytes. + +- Required: No +- Type: int + +### Parameter: `elasticPools.minCapacity` + +Minimal capacity that serverless pool will not shrink below, if not paused. + +- Required: No +- Type: int + +### Parameter: `elasticPools.perDatabaseSettings` + +The per database settings for the elastic pool. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`maxCapacity`](#parameter-elasticpoolsperdatabasesettingsmaxcapacity) | string | The maximum capacity any one database can consume. Examples: '0.5', '2'. | +| [`minCapacity`](#parameter-elasticpoolsperdatabasesettingsmincapacity) | string | The minimum capacity all databases are guaranteed. Examples: '0.5', '1'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoPauseDelay`](#parameter-elasticpoolsperdatabasesettingsautopausedelay) | int | Auto Pause Delay for per database within pool. | + +### Parameter: `elasticPools.perDatabaseSettings.maxCapacity` + +The maximum capacity any one database can consume. Examples: '0.5', '2'. + +- Required: Yes +- Type: string + +### Parameter: `elasticPools.perDatabaseSettings.minCapacity` + +The minimum capacity all databases are guaranteed. Examples: '0.5', '1'. + +- Required: Yes +- Type: string + +### Parameter: `elasticPools.perDatabaseSettings.autoPauseDelay` + +Auto Pause Delay for per database within pool. + +- Required: No +- Type: int + +### Parameter: `elasticPools.preferredEnclaveType` + +Type of enclave requested on the elastic pool. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Default' + 'VBS' + ] + ``` + +### Parameter: `elasticPools.sku` + +The elastic pool SKU. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-elasticpoolsskuname) | string | The name of the SKU, typically, a letter + Number code, e.g. P3. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacity`](#parameter-elasticpoolsskucapacity) | int | The capacity of the particular SKU. | +| [`family`](#parameter-elasticpoolsskufamily) | string | If the service has different generations of hardware, for the same SKU, then that can be captured here. | +| [`size`](#parameter-elasticpoolsskusize) | string | Size of the particular SKU. | +| [`tier`](#parameter-elasticpoolsskutier) | string | The tier or edition of the particular SKU, e.g. Basic, Premium. | + +### Parameter: `elasticPools.sku.name` + +The name of the SKU, typically, a letter + Number code, e.g. P3. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'BasicPool' + 'BC_DC' + 'BC_Gen5' + 'GP_DC' + 'GP_FSv2' + 'GP_Gen5' + 'HS_Gen5' + 'HS_MOPRMS' + 'HS_PRMS' + 'PremiumPool' + 'ServerlessPool' + 'StandardPool' + ] + ``` + +### Parameter: `elasticPools.sku.capacity` + +The capacity of the particular SKU. + +- Required: No +- Type: int + +### Parameter: `elasticPools.sku.family` + +If the service has different generations of hardware, for the same SKU, then that can be captured here. + +- Required: No +- Type: string + +### Parameter: `elasticPools.sku.size` + +Size of the particular SKU. + +- Required: No +- Type: string + +### Parameter: `elasticPools.sku.tier` + +The tier or edition of the particular SKU, e.g. Basic, Premium. + +- Required: No +- Type: string + +### Parameter: `elasticPools.tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `elasticPools.zoneRedundant` + +Whether or not this elastic pool is zone redundant, which means the replicas of this elastic pool will be spread across multiple availability zones. + +- Required: No +- Type: bool + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `encryptionProtectorObj` + +The encryption protection configuration. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `federatedClientId` + +The Client id used for cross tenant CMK scenario. + +- Required: No +- Type: string + +### Parameter: `firewallRules` + +The firewall rules to create in the server. + +- Required: No +- Type: array +- Default: `[]` + ### Parameter: `isIPv6Enabled` Whether or not to enable IPv6 support for this server. @@ -1891,6 +3028,13 @@ Whether or not to enable IPv6 support for this server. ] ``` +### Parameter: `keyId` + +A CMK URI of the key to use for encryption. + +- Required: No +- Type: string + ### Parameter: `keys` The keys to configure. @@ -1955,7 +3099,7 @@ The managed identity definition for this resource. | Parameter | Type | Description | | :-- | :-- | :-- | | [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | ### Parameter: `managedIdentities.systemAssigned` @@ -1966,7 +3110,7 @@ Enables system assigned managed identity on the resource. ### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. - Required: No - Type: array @@ -2005,22 +3149,22 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the Private Endpoint IP configuration is included. | | [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | -| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the Private Endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. | | [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | -| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the Private Endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | -| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS zone group to configure for the private endpoint. | +| [`name`](#parameter-privateendpointsname) | string | The name of the Private Endpoint. | +| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS Zone Group to configure for the Private Endpoint. | | [`privateLinkServiceConnectionName`](#parameter-privateendpointsprivatelinkserviceconnectionname) | string | The name of the private link connection to create. | -| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. | +| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | -| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/Resource Groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -2031,7 +3175,7 @@ Resource ID of the subnet where the endpoint needs to be created. ### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` -Application security groups in which the private endpoint IP configuration is included. +Application security groups in which the Private Endpoint IP configuration is included. - Required: No - Type: array @@ -2047,15 +3191,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -2064,9 +3206,16 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` -The custom name of the network interface attached to the private endpoint. +The custom name of the network interface attached to the Private Endpoint. - Required: No - Type: string @@ -2080,7 +3229,7 @@ Enable/Disable usage telemetry for module. ### Parameter: `privateEndpoints.ipConfigurations` -A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. +A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. - Required: No - Type: array @@ -2144,7 +3293,7 @@ If Manual Private Link Connection is required. ### Parameter: `privateEndpoints.location` -The location to deploy the private endpoint to. +The location to deploy the Private Endpoint to. - Required: No - Type: string @@ -2194,14 +3343,14 @@ A message passed to the owner of the remote resource with the manual connection ### Parameter: `privateEndpoints.name` -The name of the private endpoint. +The name of the Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.privateDnsZoneGroup` -The private DNS zone group to configure for the private endpoint. +The private DNS Zone Group to configure for the Private Endpoint. - Required: No - Type: object @@ -2210,7 +3359,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -2220,7 +3369,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -2235,7 +3384,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -2246,7 +3395,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -2267,7 +3416,7 @@ The name of the private link connection to create. ### Parameter: `privateEndpoints.resourceGroupName` -Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. +Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. - Required: No - Type: string @@ -2382,14 +3531,14 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". +The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.tags` -Tags to be applied on all resources/resource groups in this deployment. +Tags to be applied on all resources/Resource Groups in this deployment. - Required: No - Type: object @@ -2628,6 +3777,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Notes diff --git a/avm/res/sql/server/audit-settings/README.md b/avm/res/sql/server/audit-settings/README.md index 0192be9674..79759eb42a 100644 --- a/avm/res/sql/server/audit-settings/README.md +++ b/avm/res/sql/server/audit-settings/README.md @@ -22,7 +22,6 @@ This module deploys an Azure SQL Server Audit Settings. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | The name of the audit settings. | -| [`state`](#parameter-state) | string | The resource group of the SQL Server. Required if the template is used in a standalone deployment. | **Conditional parameters** @@ -41,6 +40,7 @@ This module deploys an Azure SQL Server Audit Settings. | [`isStorageSecondaryKeyInUse`](#parameter-isstoragesecondarykeyinuse) | bool | Specifies whether storageAccountAccessKey value is the storage's secondary key. | | [`queueDelayMs`](#parameter-queuedelayms) | int | Specifies the amount of time in milliseconds that can elapse before audit actions are forced to be processed. | | [`retentionDays`](#parameter-retentiondays) | int | Specifies the number of days to keep in the audit logs in the storage account. | +| [`state`](#parameter-state) | string | Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required. | | [`storageAccountResourceId`](#parameter-storageaccountresourceid) | string | A blob storage to hold the auditing storage account. | ### Parameter: `name` @@ -50,20 +50,6 @@ The name of the audit settings. - Required: Yes - Type: string -### Parameter: `state` - -The resource group of the SQL Server. Required if the template is used in a standalone deployment. - -- Required: Yes -- Type: string -- Allowed: - ```Bicep - [ - 'Disabled' - 'Enabled' - ] - ``` - ### Parameter: `serverName` The Name of SQL Server. Required if the template is used in a standalone deployment. @@ -77,6 +63,14 @@ Specifies the Actions-Groups and Actions to audit. - Required: No - Type: array +- Default: + ```Bicep + [ + 'BATCH_COMPLETED_GROUP' + 'FAILED_DATABASE_AUTHENTICATION_GROUP' + 'SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP' + ] + ``` ### Parameter: `isAzureMonitorTargetEnabled` @@ -84,7 +78,7 @@ Specifies whether audit events are sent to Azure Monitor. - Required: No - Type: bool -- Default: `False` +- Default: `True` ### Parameter: `isDevopsAuditEnabled` @@ -92,6 +86,7 @@ Specifies the state of devops audit. If state is Enabled, devops logs will be se - Required: No - Type: bool +- Default: `False` ### Parameter: `isManagedIdentityInUse` @@ -107,6 +102,7 @@ Specifies whether storageAccountAccessKey value is the storage's secondary key. - Required: No - Type: bool +- Default: `False` ### Parameter: `queueDelayMs` @@ -114,6 +110,7 @@ Specifies the amount of time in milliseconds that can elapse before audit action - Required: No - Type: int +- Default: `1000` ### Parameter: `retentionDays` @@ -121,6 +118,22 @@ Specifies the number of days to keep in the audit logs in the storage account. - Required: No - Type: int +- Default: `90` + +### Parameter: `state` + +Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required. + +- Required: No +- Type: string +- Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` ### Parameter: `storageAccountResourceId` diff --git a/avm/res/sql/server/audit-settings/main.bicep b/avm/res/sql/server/audit-settings/main.bicep index 4419b942b0..8d23380517 100644 --- a/avm/res/sql/server/audit-settings/main.bicep +++ b/avm/res/sql/server/audit-settings/main.bicep @@ -8,33 +8,37 @@ param name string @description('Conditional. The Name of SQL Server. Required if the template is used in a standalone deployment.') param serverName string -@description('Required. The resource group of the SQL Server. Required if the template is used in a standalone deployment.') +@description('Optional. Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required.') @allowed([ 'Enabled' 'Disabled' ]) -param state string +param state string = 'Enabled' @description('Optional. Specifies the Actions-Groups and Actions to audit.') -param auditActionsAndGroups array? +param auditActionsAndGroups string[] = [ + 'BATCH_COMPLETED_GROUP' + 'SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP' + 'FAILED_DATABASE_AUTHENTICATION_GROUP' +] @description('Optional. Specifies whether audit events are sent to Azure Monitor.') -param isAzureMonitorTargetEnabled bool = false +param isAzureMonitorTargetEnabled bool = true @description('Optional. Specifies the state of devops audit. If state is Enabled, devops logs will be sent to Azure Monitor.') -param isDevopsAuditEnabled bool? +param isDevopsAuditEnabled bool = false @description('Optional. Specifies whether Managed Identity is used to access blob storage.') param isManagedIdentityInUse bool = false @description('Optional. Specifies whether storageAccountAccessKey value is the storage\'s secondary key.') -param isStorageSecondaryKeyInUse bool? +param isStorageSecondaryKeyInUse bool = false @description('Optional. Specifies the amount of time in milliseconds that can elapse before audit actions are forced to be processed.') -param queueDelayMs int? +param queueDelayMs int = 1000 @description('Optional. Specifies the number of days to keep in the audit logs in the storage account.') -param retentionDays int? +param retentionDays int = 90 @description('Optional. A blob storage to hold the auditing storage account.') param storageAccountResourceId string = '' diff --git a/avm/res/sql/server/audit-settings/main.json b/avm/res/sql/server/audit-settings/main.json index e18c9a0494..4c12fe1854 100644 --- a/avm/res/sql/server/audit-settings/main.json +++ b/avm/res/sql/server/audit-settings/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4165841300638093382" + "version": "0.30.23.60470", + "templateHash": "6303070680265885029" }, "name": "Azure SQL Server Audit Settings", "description": "This module deploys an Azure SQL Server Audit Settings.", @@ -27,31 +27,39 @@ }, "state": { "type": "string", + "defaultValue": "Enabled", "allowedValues": [ "Enabled", "Disabled" ], "metadata": { - "description": "Required. The resource group of the SQL Server. Required if the template is used in a standalone deployment." + "description": "Optional. Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required." } }, "auditActionsAndGroups": { "type": "array", - "nullable": true, + "items": { + "type": "string" + }, + "defaultValue": [ + "BATCH_COMPLETED_GROUP", + "SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP", + "FAILED_DATABASE_AUTHENTICATION_GROUP" + ], "metadata": { "description": "Optional. Specifies the Actions-Groups and Actions to audit." } }, "isAzureMonitorTargetEnabled": { "type": "bool", - "defaultValue": false, + "defaultValue": true, "metadata": { "description": "Optional. Specifies whether audit events are sent to Azure Monitor." } }, "isDevopsAuditEnabled": { "type": "bool", - "nullable": true, + "defaultValue": false, "metadata": { "description": "Optional. Specifies the state of devops audit. If state is Enabled, devops logs will be sent to Azure Monitor." } @@ -65,21 +73,21 @@ }, "isStorageSecondaryKeyInUse": { "type": "bool", - "nullable": true, + "defaultValue": false, "metadata": { "description": "Optional. Specifies whether storageAccountAccessKey value is the storage's secondary key." } }, "queueDelayMs": { "type": "int", - "nullable": true, + "defaultValue": 1000, "metadata": { "description": "Optional. Specifies the amount of time in milliseconds that can elapse before audit actions are forced to be processed." } }, "retentionDays": { "type": "int", - "nullable": true, + "defaultValue": 90, "metadata": { "description": "Optional. Specifies the number of days to keep in the audit logs in the storage account." } @@ -144,8 +152,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17251889896692066430" + "version": "0.30.23.60470", + "templateHash": "13956215614091387428" } }, "parameters": { diff --git a/avm/res/sql/server/database/README.md b/avm/res/sql/server/database/README.md index 1abb8e303b..9783dcfb7a 100644 --- a/avm/res/sql/server/database/README.md +++ b/avm/res/sql/server/database/README.md @@ -7,6 +7,7 @@ This module deploys an Azure SQL Server Database. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -14,7 +15,7 @@ This module deploys an Azure SQL Server Database. | :-- | :-- | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | | `Microsoft.Sql/servers/databases` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/databases) | -| `Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies) | +| `Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies` | [2023-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/2023-05-01-preview/servers/databases/backupLongTermRetentionPolicies) | | `Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies) | ## Parameters @@ -36,33 +37,43 @@ This module deploys an Azure SQL Server Database. | Parameter | Type | Description | | :-- | :-- | :-- | | [`autoPauseDelay`](#parameter-autopausedelay) | int | Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled. | +| [`availabilityZone`](#parameter-availabilityzone) | string | Specifies the availability zone the database is pinned to. | | [`backupLongTermRetentionPolicy`](#parameter-backuplongtermretentionpolicy) | object | The long term backup retention policy to create for the database. | | [`backupShortTermRetentionPolicy`](#parameter-backupshorttermretentionpolicy) | object | The short term backup retention policy to create for the database. | +| [`catalogCollation`](#parameter-catalogcollation) | string | Collation of the metadata catalog. | | [`collation`](#parameter-collation) | string | The collation of the database. | | [`createMode`](#parameter-createmode) | string | Specifies the mode of database creation. | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | -| [`elasticPoolId`](#parameter-elasticpoolid) | string | The resource ID of the elastic pool containing this database. | +| [`elasticPoolResourceId`](#parameter-elasticpoolresourceid) | string | The resource ID of the elastic pool containing this database. | +| [`encryptionProtector`](#parameter-encryptionprotector) | string | The azure key vault URI of the database if it's configured with per Database Customer Managed Keys. | +| [`encryptionProtectorAutoRotation`](#parameter-encryptionprotectorautorotation) | bool | The flag to enable or disable auto rotation of database encryption protector AKV key. | +| [`federatedClientId`](#parameter-federatedclientid) | string | The Client id used for cross tenant per database CMK scenario. | +| [`freeLimitExhaustionBehavior`](#parameter-freelimitexhaustionbehavior) | string | Specifies the behavior when monthly free limits are exhausted for the free database. | | [`highAvailabilityReplicaCount`](#parameter-highavailabilityreplicacount) | int | The number of readonly secondary replicas associated with the database. | | [`isLedgerOn`](#parameter-isledgeron) | bool | 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`](#parameter-licensetype) | string | The license type to apply for this database. | | [`location`](#parameter-location) | string | Location for all resources. | +| [`longTermRetentionBackupResourceId`](#parameter-longtermretentionbackupresourceid) | string | The resource identifier of the long term retention backup associated with create operation of this database. | | [`maintenanceConfigurationId`](#parameter-maintenanceconfigurationid) | string | Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur. | +| [`manualCutover`](#parameter-manualcutover) | bool | Whether or not customer controlled manual cutover needs to be done during Update Database operation to Hyperscale tier. | | [`maxSizeBytes`](#parameter-maxsizebytes) | int | The max size of the database expressed in bytes. | | [`minCapacity`](#parameter-mincapacity) | string | Minimal capacity that database will always have allocated. | +| [`performCutover`](#parameter-performcutover) | bool | To trigger customer controlled manual cutover during the wait state while Scaling operation is in progress. | | [`preferredEnclaveType`](#parameter-preferredenclavetype) | string | Type of enclave requested on the database i.e. Default or VBS enclaves. | | [`readScale`](#parameter-readscale) | string | The state of read-only routing. | -| [`recoveryServicesRecoveryPointResourceId`](#parameter-recoveryservicesrecoverypointresourceid) | string | Resource ID of backup if createMode set to RestoreLongTermRetentionBackup. | +| [`recoverableDatabaseResourceId`](#parameter-recoverabledatabaseresourceid) | string | The resource identifier of the recoverable database associated with create operation of this database. | +| [`recoveryServicesRecoveryPointResourceId`](#parameter-recoveryservicesrecoverypointresourceid) | string | The resource identifier of the recovery point associated with create operation of this database. | | [`requestedBackupStorageRedundancy`](#parameter-requestedbackupstorageredundancy) | string | The storage account type to be used to store backups for this database. | +| [`restorableDroppedDatabaseResourceId`](#parameter-restorabledroppeddatabaseresourceid) | string | The resource identifier of the restorable dropped database associated with create operation of this database. | | [`restorePointInTime`](#parameter-restorepointintime) | string | Point in time (ISO8601 format) of the source database to restore when createMode set to Restore or PointInTimeRestore. | | [`sampleName`](#parameter-samplename) | string | The name of the sample schema to apply when creating this database. | -| [`skuCapacity`](#parameter-skucapacity) | int | Capacity of the particular SKU. | -| [`skuFamily`](#parameter-skufamily) | string | If the service has different generations of hardware, for the same SKU, then that can be captured here. | -| [`skuName`](#parameter-skuname) | string | The name of the SKU. | -| [`skuSize`](#parameter-skusize) | string | Size of the particular SKU. | -| [`skuTier`](#parameter-skutier) | string | The skuTier or edition of the particular SKU. | +| [`secondaryType`](#parameter-secondarytype) | string | The secondary type of the database if it is a secondary. | +| [`sku`](#parameter-sku) | object | The database SKU. | | [`sourceDatabaseDeletionDate`](#parameter-sourcedatabasedeletiondate) | string | The time that the database was deleted when restoring a deleted database. | -| [`sourceDatabaseResourceId`](#parameter-sourcedatabaseresourceid) | string | Resource ID of database if createMode set to Copy, Secondary, PointInTimeRestore, Recovery or Restore. | +| [`sourceDatabaseResourceId`](#parameter-sourcedatabaseresourceid) | string | The resource identifier of the source database associated with create operation of this database. | +| [`sourceResourceId`](#parameter-sourceresourceid) | string | The resource identifier of the source associated with the create operation of this database. | | [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`useFreeLimit`](#parameter-usefreelimit) | bool | Whether or not the database uses free monthly limits. Allowed on one database in a subscription. | | [`zoneRedundant`](#parameter-zoneredundant) | bool | Whether or not this database is zone redundant. | ### Parameter: `name` @@ -85,7 +96,24 @@ Time in minutes after which database is automatically paused. A value of -1 mean - Required: No - Type: int -- Default: `0` +- Default: `-1` + +### Parameter: `availabilityZone` + +Specifies the availability zone the database is pinned to. + +- Required: No +- Type: string +- Default: `'NoPreference'` +- Allowed: + ```Bicep + [ + '1' + '2' + '3' + 'NoPreference' + ] + ``` ### Parameter: `backupLongTermRetentionPolicy` @@ -93,7 +121,66 @@ The long term backup retention policy to create for the database. - Required: No - Type: object -- Default: `{}` + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`backupStorageAccessTier`](#parameter-backuplongtermretentionpolicybackupstorageaccesstier) | string | The BackupStorageAccessTier for the LTR backups. | +| [`makeBackupsImmutable`](#parameter-backuplongtermretentionpolicymakebackupsimmutable) | bool | The setting whether to make LTR backups immutable. | +| [`monthlyRetention`](#parameter-backuplongtermretentionpolicymonthlyretention) | string | Monthly retention in ISO 8601 duration format. | +| [`weeklyRetention`](#parameter-backuplongtermretentionpolicyweeklyretention) | string | Weekly retention in ISO 8601 duration format. | +| [`weekOfYear`](#parameter-backuplongtermretentionpolicyweekofyear) | int | Week of year backup to keep for yearly retention. | +| [`yearlyRetention`](#parameter-backuplongtermretentionpolicyyearlyretention) | string | Yearly retention in ISO 8601 duration format. | + +### Parameter: `backupLongTermRetentionPolicy.backupStorageAccessTier` + +The BackupStorageAccessTier for the LTR backups. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Archive' + 'Hot' + ] + ``` + +### Parameter: `backupLongTermRetentionPolicy.makeBackupsImmutable` + +The setting whether to make LTR backups immutable. + +- Required: No +- Type: bool + +### Parameter: `backupLongTermRetentionPolicy.monthlyRetention` + +Monthly retention in ISO 8601 duration format. + +- Required: No +- Type: string + +### Parameter: `backupLongTermRetentionPolicy.weeklyRetention` + +Weekly retention in ISO 8601 duration format. + +- Required: No +- Type: string + +### Parameter: `backupLongTermRetentionPolicy.weekOfYear` + +Week of year backup to keep for yearly retention. + +- Required: No +- Type: int + +### Parameter: `backupLongTermRetentionPolicy.yearlyRetention` + +Yearly retention in ISO 8601 duration format. + +- Required: No +- Type: string ### Parameter: `backupShortTermRetentionPolicy` @@ -101,7 +188,35 @@ The short term backup retention policy to create for the database. - Required: No - Type: object -- Default: `{}` + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`diffBackupIntervalInHours`](#parameter-backupshorttermretentionpolicydiffbackupintervalinhours) | int | Differential backup interval in hours. For Hyperscale tiers this value will be ignored. | +| [`retentionDays`](#parameter-backupshorttermretentionpolicyretentiondays) | int | Point-in-time retention in days. | + +### Parameter: `backupShortTermRetentionPolicy.diffBackupIntervalInHours` + +Differential backup interval in hours. For Hyperscale tiers this value will be ignored. + +- Required: No +- Type: int + +### Parameter: `backupShortTermRetentionPolicy.retentionDays` + +Point-in-time retention in days. + +- Required: No +- Type: int + +### Parameter: `catalogCollation` + +Collation of the metadata catalog. + +- Required: No +- Type: string +- Default: `'DATABASE_DEFAULT'` ### Parameter: `collation` @@ -127,6 +242,8 @@ Specifies the mode of database creation. 'PointInTimeRestore' 'Recovery' 'Restore' + 'RestoreExternalBackup' + 'RestoreExternalBackupSecondary' 'RestoreLongTermRetentionBackup' 'Secondary' ] @@ -149,7 +266,7 @@ The diagnostic settings of the service. | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -259,7 +376,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -278,13 +395,47 @@ Resource ID of the diagnostic log analytics workspace. For security reasons, it - Required: No - Type: string -### Parameter: `elasticPoolId` +### Parameter: `elasticPoolResourceId` The resource ID of the elastic pool containing this database. - Required: No - Type: string -- Default: `''` + +### Parameter: `encryptionProtector` + +The azure key vault URI of the database if it's configured with per Database Customer Managed Keys. + +- Required: No +- Type: string + +### Parameter: `encryptionProtectorAutoRotation` + +The flag to enable or disable auto rotation of database encryption protector AKV key. + +- Required: No +- Type: bool + +### Parameter: `federatedClientId` + +The Client id used for cross tenant per database CMK scenario. + +- Required: No +- Type: string + +### Parameter: `freeLimitExhaustionBehavior` + +Specifies the behavior when monthly free limits are exhausted for the free database. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AutoPause' + 'BillOverUsage' + ] + ``` ### Parameter: `highAvailabilityReplicaCount` @@ -308,7 +459,13 @@ The license type to apply for this database. - Required: No - Type: string -- Default: `''` +- Allowed: + ```Bicep + [ + 'BasePrice' + 'LicenseIncluded' + ] + ``` ### Parameter: `location` @@ -318,6 +475,13 @@ Location for all resources. - Type: string - Default: `[resourceGroup().location]` +### Parameter: `longTermRetentionBackupResourceId` + +The resource identifier of the long term retention backup associated with create operation of this database. + +- Required: No +- Type: string + ### Parameter: `maintenanceConfigurationId` Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur. @@ -325,6 +489,13 @@ Maintenance configuration ID assigned to the database. This configuration define - Required: No - Type: string +### Parameter: `manualCutover` + +Whether or not customer controlled manual cutover needs to be done during Update Database operation to Hyperscale tier. + +- Required: No +- Type: bool + ### Parameter: `maxSizeBytes` The max size of the database expressed in bytes. @@ -339,7 +510,14 @@ Minimal capacity that database will always have allocated. - Required: No - Type: string -- Default: `''` +- Default: `'0'` + +### Parameter: `performCutover` + +To trigger customer controlled manual cutover during the wait state while Scaling operation is in progress. + +- Required: No +- Type: bool ### Parameter: `preferredEnclaveType` @@ -347,11 +525,9 @@ Type of enclave requested on the database i.e. Default or VBS enclaves. - Required: No - Type: string -- Default: `''` - Allowed: ```Bicep [ - '' 'Default' 'VBS' ] @@ -372,13 +548,19 @@ The state of read-only routing. ] ``` +### Parameter: `recoverableDatabaseResourceId` + +The resource identifier of the recoverable database associated with create operation of this database. + +- Required: No +- Type: string + ### Parameter: `recoveryServicesRecoveryPointResourceId` -Resource ID of backup if createMode set to RestoreLongTermRetentionBackup. +The resource identifier of the recovery point associated with create operation of this database. - Required: No - Type: string -- Default: `''` ### Parameter: `requestedBackupStorageRedundancy` @@ -386,24 +568,30 @@ The storage account type to be used to store backups for this database. - Required: No - Type: string -- Default: `''` +- Default: `'Local'` - Allowed: ```Bicep [ - '' 'Geo' + 'GeoZone' 'Local' 'Zone' ] ``` +### Parameter: `restorableDroppedDatabaseResourceId` + +The resource identifier of the restorable dropped database associated with create operation of this database. + +- Required: No +- Type: string + ### Parameter: `restorePointInTime` Point in time (ISO8601 format) of the source database to restore when createMode set to Restore or PointInTimeRestore. - Required: No - Type: string -- Default: `''` ### Parameter: `sampleName` @@ -413,44 +601,84 @@ The name of the sample schema to apply when creating this database. - Type: string - Default: `''` -### Parameter: `skuCapacity` +### Parameter: `secondaryType` -Capacity of the particular SKU. +The secondary type of the database if it is a secondary. - Required: No -- Type: int +- Type: string +- Allowed: + ```Bicep + [ + 'Geo' + 'Named' + 'Standby' + ] + ``` -### Parameter: `skuFamily` +### Parameter: `sku` -If the service has different generations of hardware, for the same SKU, then that can be captured here. +The database SKU. - Required: No +- Type: object +- Default: + ```Bicep + { + name: 'GP_Gen5_2' + tier: 'GeneralPurpose' + } + ``` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-skuname) | string | The name of the SKU, typically, a letter + Number code, e.g. P3. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacity`](#parameter-skucapacity) | int | The capacity of the particular SKU. | +| [`family`](#parameter-skufamily) | string | If the service has different generations of hardware, for the same SKU, then that can be captured here. | +| [`size`](#parameter-skusize) | string | Size of the particular SKU. | +| [`tier`](#parameter-skutier) | string | The tier or edition of the particular SKU, e.g. Basic, Premium. | + +### Parameter: `sku.name` + +The name of the SKU, typically, a letter + Number code, e.g. P3. + +- Required: Yes - Type: string -- Default: `''` -### Parameter: `skuName` +### Parameter: `sku.capacity` -The name of the SKU. +The capacity of the particular SKU. + +- Required: No +- Type: int + +### Parameter: `sku.family` + +If the service has different generations of hardware, for the same SKU, then that can be captured here. - Required: No - Type: string -- Default: `'GP_Gen5_2'` -### Parameter: `skuSize` +### Parameter: `sku.size` Size of the particular SKU. - Required: No - Type: string -- Default: `''` -### Parameter: `skuTier` +### Parameter: `sku.tier` -The skuTier or edition of the particular SKU. +The tier or edition of the particular SKU, e.g. Basic, Premium. - Required: No - Type: string -- Default: `'GeneralPurpose'` ### Parameter: `sourceDatabaseDeletionDate` @@ -458,15 +686,20 @@ The time that the database was deleted when restoring a deleted database. - Required: No - Type: string -- Default: `''` ### Parameter: `sourceDatabaseResourceId` -Resource ID of database if createMode set to Copy, Secondary, PointInTimeRestore, Recovery or Restore. +The resource identifier of the source database associated with create operation of this database. + +- Required: No +- Type: string + +### Parameter: `sourceResourceId` + +The resource identifier of the source associated with the create operation of this database. - Required: No - Type: string -- Default: `''` ### Parameter: `tags` @@ -475,6 +708,13 @@ Tags of the resource. - Required: No - Type: object +### Parameter: `useFreeLimit` + +Whether or not the database uses free monthly limits. Allowed on one database in a subscription. + +- Required: No +- Type: bool + ### Parameter: `zoneRedundant` Whether or not this database is zone redundant. @@ -491,3 +731,11 @@ Whether or not this database is zone redundant. | `name` | string | The name of the deployed database. | | `resourceGroupName` | string | The resource group of the deployed database. | | `resourceId` | string | The resource ID of the deployed database. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/sql/server/database/backup-long-term-retention-policy/README.md b/avm/res/sql/server/database/backup-long-term-retention-policy/README.md index cc8f638db5..4e9e070b02 100644 --- a/avm/res/sql/server/database/backup-long-term-retention-policy/README.md +++ b/avm/res/sql/server/database/backup-long-term-retention-policy/README.md @@ -12,7 +12,7 @@ This module deploys an Azure SQL Server Database Long-Term Backup Retention Poli | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies) | +| `Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies` | [2023-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/2023-05-01-preview/servers/databases/backupLongTermRetentionPolicies) | ## Parameters @@ -27,8 +27,10 @@ This module deploys an Azure SQL Server Database Long-Term Backup Retention Poli | Parameter | Type | Description | | :-- | :-- | :-- | -| [`monthlyRetention`](#parameter-monthlyretention) | string | Weekly retention in ISO 8601 duration format. | -| [`weeklyRetention`](#parameter-weeklyretention) | string | Monthly retention in ISO 8601 duration format. | +| [`backupStorageAccessTier`](#parameter-backupstorageaccesstier) | string | The BackupStorageAccessTier for the LTR backups. | +| [`makeBackupsImmutable`](#parameter-makebackupsimmutable) | bool | The setting whether to make LTR backups immutable. | +| [`monthlyRetention`](#parameter-monthlyretention) | string | Monthly retention in ISO 8601 duration format. | +| [`weeklyRetention`](#parameter-weeklyretention) | string | Weekly retention in ISO 8601 duration format. | | [`weekOfYear`](#parameter-weekofyear) | int | Week of year backup to keep for yearly retention. | | [`yearlyRetention`](#parameter-yearlyretention) | string | Yearly retention in ISO 8601 duration format. | @@ -46,21 +48,40 @@ The name of the parent SQL Server. - Required: Yes - Type: string +### Parameter: `backupStorageAccessTier` + +The BackupStorageAccessTier for the LTR backups. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Archive' + 'Hot' + ] + ``` + +### Parameter: `makeBackupsImmutable` + +The setting whether to make LTR backups immutable. + +- Required: No +- Type: bool + ### Parameter: `monthlyRetention` -Weekly retention in ISO 8601 duration format. +Monthly retention in ISO 8601 duration format. - Required: No - Type: string -- Default: `''` ### Parameter: `weeklyRetention` -Monthly retention in ISO 8601 duration format. +Weekly retention in ISO 8601 duration format. - Required: No - Type: string -- Default: `''` ### Parameter: `weekOfYear` @@ -76,7 +97,6 @@ Yearly retention in ISO 8601 duration format. - Required: No - Type: string -- Default: `''` ## Outputs diff --git a/avm/res/sql/server/database/backup-long-term-retention-policy/main.bicep b/avm/res/sql/server/database/backup-long-term-retention-policy/main.bicep index 86a4e8f0dd..e143e98f53 100644 --- a/avm/res/sql/server/database/backup-long-term-retention-policy/main.bicep +++ b/avm/res/sql/server/database/backup-long-term-retention-policy/main.bicep @@ -8,17 +8,23 @@ param serverName string @description('Required. The name of the parent database.') param databaseName string +@description('Optional. The BackupStorageAccessTier for the LTR backups.') +param backupStorageAccessTier 'Archive' | 'Hot'? + +@description('Optional. The setting whether to make LTR backups immutable.') +param makeBackupsImmutable bool? + @description('Optional. Monthly retention in ISO 8601 duration format.') -param weeklyRetention string = '' +param monthlyRetention string? @description('Optional. Weekly retention in ISO 8601 duration format.') -param monthlyRetention string = '' +param weeklyRetention string? @description('Optional. Week of year backup to keep for yearly retention.') param weekOfYear int = 1 @description('Optional. Yearly retention in ISO 8601 duration format.') -param yearlyRetention string = '' +param yearlyRetention string? resource server 'Microsoft.Sql/servers@2023-08-01-preview' existing = { name: serverName @@ -28,10 +34,12 @@ resource server 'Microsoft.Sql/servers@2023-08-01-preview' existing = { } } -resource backupLongTermRetentionPolicy 'Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies@2023-08-01-preview' = { +resource backupLongTermRetentionPolicy 'Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies@2023-05-01-preview' = { name: 'default' parent: server::database properties: { + backupStorageAccessTier: backupStorageAccessTier + makeBackupsImmutable: makeBackupsImmutable monthlyRetention: monthlyRetention weeklyRetention: weeklyRetention weekOfYear: weekOfYear diff --git a/avm/res/sql/server/database/backup-long-term-retention-policy/main.json b/avm/res/sql/server/database/backup-long-term-retention-policy/main.json index b54683c3bc..aa4ac7652a 100644 --- a/avm/res/sql/server/database/backup-long-term-retention-policy/main.json +++ b/avm/res/sql/server/database/backup-long-term-retention-policy/main.json @@ -1,11 +1,12 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2778016138108001251" + "version": "0.30.23.60470", + "templateHash": "841731129374883266" }, "name": "SQL Server Database Long Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Long-Term Backup Retention Policy.", @@ -24,16 +25,34 @@ "description": "Required. The name of the parent database." } }, - "weeklyRetention": { + "backupStorageAccessTier": { "type": "string", - "defaultValue": "", + "allowedValues": [ + "Archive", + "Hot" + ], + "nullable": true, "metadata": { - "description": "Optional. Monthly retention in ISO 8601 duration format." + "description": "Optional. The BackupStorageAccessTier for the LTR backups." + } + }, + "makeBackupsImmutable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The setting whether to make LTR backups immutable." } }, "monthlyRetention": { "type": "string", - "defaultValue": "", + "nullable": true, + "metadata": { + "description": "Optional. Monthly retention in ISO 8601 duration format." + } + }, + "weeklyRetention": { + "type": "string", + "nullable": true, "metadata": { "description": "Optional. Weekly retention in ISO 8601 duration format." } @@ -47,25 +66,45 @@ }, "yearlyRetention": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Yearly retention in ISO 8601 duration format." } } }, - "resources": [ - { - "type": "Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies", + "resources": { + "server::database": { + "existing": true, + "type": "Microsoft.Sql/servers/databases", "apiVersion": "2023-08-01-preview", + "name": "[format('{0}/{1}', parameters('serverName'), parameters('databaseName'))]", + "dependsOn": [ + "server" + ] + }, + "server": { + "existing": true, + "type": "Microsoft.Sql/servers", + "apiVersion": "2023-08-01-preview", + "name": "[parameters('serverName')]" + }, + "backupLongTermRetentionPolicy": { + "type": "Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies", + "apiVersion": "2023-05-01-preview", "name": "[format('{0}/{1}/{2}', parameters('serverName'), parameters('databaseName'), 'default')]", "properties": { + "backupStorageAccessTier": "[parameters('backupStorageAccessTier')]", + "makeBackupsImmutable": "[parameters('makeBackupsImmutable')]", "monthlyRetention": "[parameters('monthlyRetention')]", "weeklyRetention": "[parameters('weeklyRetention')]", "weekOfYear": "[parameters('weekOfYear')]", "yearlyRetention": "[parameters('yearlyRetention')]" - } + }, + "dependsOn": [ + "server::database" + ] } - ], + }, "outputs": { "resourceGroupName": { "type": "string", diff --git a/avm/res/sql/server/database/backup-short-term-retention-policy/README.md b/avm/res/sql/server/database/backup-short-term-retention-policy/README.md index 9f742d71b4..711861fcd1 100644 --- a/avm/res/sql/server/database/backup-short-term-retention-policy/README.md +++ b/avm/res/sql/server/database/backup-short-term-retention-policy/README.md @@ -27,7 +27,7 @@ This module deploys an Azure SQL Server Database Short-Term Backup Retention Pol | Parameter | Type | Description | | :-- | :-- | :-- | -| [`diffBackupIntervalInHours`](#parameter-diffbackupintervalinhours) | int | Differential backup interval in hours. | +| [`diffBackupIntervalInHours`](#parameter-diffbackupintervalinhours) | int | Differential backup interval in hours. For Hyperscal tiers this value will be ignored. | | [`retentionDays`](#parameter-retentiondays) | int | Poin-in-time retention in days. | ### Parameter: `databaseName` @@ -46,7 +46,7 @@ The name of the parent SQL Server. ### Parameter: `diffBackupIntervalInHours` -Differential backup interval in hours. +Differential backup interval in hours. For Hyperscal tiers this value will be ignored. - Required: No - Type: int diff --git a/avm/res/sql/server/database/backup-short-term-retention-policy/main.bicep b/avm/res/sql/server/database/backup-short-term-retention-policy/main.bicep index e5154bd1f2..fc3321c8ea 100644 --- a/avm/res/sql/server/database/backup-short-term-retention-policy/main.bicep +++ b/avm/res/sql/server/database/backup-short-term-retention-policy/main.bicep @@ -8,16 +8,16 @@ param serverName string @description('Required. The name of the parent database.') param databaseName string -@description('Optional. Differential backup interval in hours.') +@description('Optional. Differential backup interval in hours. For Hyperscal tiers this value will be ignored.') param diffBackupIntervalInHours int = 24 @description('Optional. Poin-in-time retention in days.') param retentionDays int = 7 -resource server 'Microsoft.Sql/servers@2022-05-01-preview' existing = { +resource server 'Microsoft.Sql/servers@2023-08-01-preview' existing = { name: serverName - resource database 'databases@2022-05-01-preview' existing = { + resource database 'databases@2023-08-01-preview' existing = { name: databaseName } } @@ -26,7 +26,7 @@ resource backupShortTermRetentionPolicy 'Microsoft.Sql/servers/databases/backupS name: 'default' parent: server::database properties: { - diffBackupIntervalInHours: diffBackupIntervalInHours + diffBackupIntervalInHours: server::database.sku.tier == 'Hyperscale' ? null : diffBackupIntervalInHours retentionDays: retentionDays } } diff --git a/avm/res/sql/server/database/backup-short-term-retention-policy/main.json b/avm/res/sql/server/database/backup-short-term-retention-policy/main.json index 842e54ba64..9b5484f2d3 100644 --- a/avm/res/sql/server/database/backup-short-term-retention-policy/main.json +++ b/avm/res/sql/server/database/backup-short-term-retention-policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8635162595153731245" + "version": "0.30.23.60470", + "templateHash": "14890409200962565555" }, "name": "Azure SQL Server Database Short Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Short-Term Backup Retention Policy.", @@ -28,7 +28,7 @@ "type": "int", "defaultValue": 24, "metadata": { - "description": "Optional. Differential backup interval in hours." + "description": "Optional. Differential backup interval in hours. For Hyperscal tiers this value will be ignored." } }, "retentionDays": { @@ -45,7 +45,7 @@ "apiVersion": "2023-08-01-preview", "name": "[format('{0}/{1}/{2}', parameters('serverName'), parameters('databaseName'), 'default')]", "properties": { - "diffBackupIntervalInHours": "[parameters('diffBackupIntervalInHours')]", + "diffBackupIntervalInHours": "[if(equals(reference(resourceId('Microsoft.Sql/servers/databases', parameters('serverName'), parameters('databaseName')), '2023-08-01-preview', 'full').sku.tier, 'Hyperscale'), null(), parameters('diffBackupIntervalInHours'))]", "retentionDays": "[parameters('retentionDays')]" } } diff --git a/avm/res/sql/server/database/main.bicep b/avm/res/sql/server/database/main.bicep index 8919f4c720..0e80da6f9b 100644 --- a/avm/res/sql/server/database/main.bicep +++ b/avm/res/sql/server/database/main.bicep @@ -2,145 +2,148 @@ metadata name = 'SQL Server Database' metadata description = 'This module deploys an Azure SQL Server Database.' metadata owner = 'Azure/module-maintainers' +// START OF DATABASE PROPERTIES + @description('Required. The name of the database.') param name string @description('Conditional. The name of the parent SQL Server. Required if the template is used in a standalone deployment.') param serverName string +@description('Optional. The database SKU.') +param sku databaseSkuType = { + name: 'GP_Gen5_2' + tier: 'GeneralPurpose' +} + +@description('Optional. Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled.') +param autoPauseDelay int = -1 + +@description('Optional. Specifies the availability zone the database is pinned to.') +param availabilityZone '1' | '2' | '3' | 'NoPreference' = 'NoPreference' + +@description('Optional. Collation of the metadata catalog.') +param catalogCollation string = 'DATABASE_DEFAULT' + @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. Specifies the mode of database creation.') +param createMode + | 'Default' + | 'Copy' + | 'OnlineSecondary' + | 'PointInTimeRestore' + | 'Recovery' + | 'Restore' + | 'RestoreExternalBackup' + | 'RestoreExternalBackupSecondary' + | 'RestoreLongTermRetentionBackup' + | 'Secondary' = 'Default' -@description('Optional. The name of the SKU.') -param skuName string = 'GP_Gen5_2' +@description('Optional. The resource ID of the elastic pool containing this database.') +param elasticPoolResourceId string? -@description('Optional. Capacity of the particular SKU.') -param skuCapacity int? +@description('Optional. The azure key vault URI of the database if it\'s configured with per Database Customer Managed Keys.') +param encryptionProtector string? -@description('Optional. Type of enclave requested on the database i.e. Default or VBS enclaves.') -@allowed([ - '' - 'Default' - 'VBS' -]) -param preferredEnclaveType string = '' +@description('Optional. The flag to enable or disable auto rotation of database encryption protector AKV key.') +param encryptionProtectorAutoRotation bool? + +@description('Optional. The Client id used for cross tenant per database CMK scenario.') +@minLength(36) +@maxLength(36) +param federatedClientId string? + +@description('Optional. Specifies the behavior when monthly free limits are exhausted for the free database.') +param freeLimitExhaustionBehavior 'AutoPause' | 'BillOverUsage'? + +@description('Optional. The number of readonly secondary replicas associated with the database.') +param highAvailabilityReplicaCount int = 0 + +@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. The license type to apply for this database.') +param licenseType 'BasePrice' | 'LicenseIncluded'? + +@description('Optional. The resource identifier of the long term retention backup associated with create operation of this database.') +param longTermRetentionBackupResourceId string? -@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. Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur.') +param maintenanceConfigurationId string? -@description('Optional. Size of the particular SKU.') -param skuSize string = '' +@description('Optional. Whether or not customer controlled manual cutover needs to be done during Update Database operation to Hyperscale tier.') +param manualCutover bool? @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. Minimal capacity that database will always have allocated.') +param minCapacity string = '0' -@description('Optional. Whether or not this database is zone redundant.') -param zoneRedundant bool = true +@description('Optional. To trigger customer controlled manual cutover during the wait state while Scaling operation is in progress.') +param performCutover bool? -@description('Optional. The license type to apply for this database.') -param licenseType string = '' +@description('Optional. Type of enclave requested on the database i.e. Default or VBS enclaves.') +param preferredEnclaveType 'Default' | 'VBS'? @description('Optional. The state of read-only routing.') -@allowed([ - 'Enabled' - 'Disabled' -]) -param readScale string = 'Disabled' +param readScale 'Enabled' | 'Disabled' = 'Disabled' -@description('Optional. The number of readonly secondary replicas associated with the database.') -param highAvailabilityReplicaCount int = 0 +@description('Optional. The resource identifier of the recoverable database associated with create operation of this database.') +param recoverableDatabaseResourceId string? -@description('Optional. Minimal capacity that database will always have allocated.') -param minCapacity string = '' - -@description('Optional. Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled.') -param autoPauseDelay int = 0 +@description('Optional. The resource identifier of the recovery point associated with create operation of this database.') +param recoveryServicesRecoveryPointResourceId string? -@description('Optional. Tags of the resource.') -param tags object? +@description('Optional. The storage account type to be used to store backups for this database.') +param requestedBackupStorageRedundancy 'Geo' | 'GeoZone' | 'Local' | 'Zone' = 'Local' -@description('Optional. The resource ID of the elastic pool containing this database.') -param elasticPoolId string = '' +@description('Optional. The resource identifier of the restorable dropped database associated with create operation of this database.') +param restorableDroppedDatabaseResourceId string? -@description('Optional. Location for all resources.') -param location string = resourceGroup().location +@description('Optional. Point in time (ISO8601 format) of the source database to restore when createMode set to Restore or PointInTimeRestore.') +param restorePointInTime string? -@description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +@description('Optional. The name of the sample schema to apply when creating this database.') +param sampleName string = '' -@description('Optional. Specifies the mode of database creation.') -@allowed([ - 'Default' - 'Copy' - 'OnlineSecondary' - 'PointInTimeRestore' - 'Recovery' - 'Restore' - 'RestoreLongTermRetentionBackup' - 'Secondary' -]) -param createMode string = 'Default' - -@description('Optional. Resource ID of database if createMode set to Copy, Secondary, PointInTimeRestore, Recovery or Restore.') -param sourceDatabaseResourceId string = '' +@description('Optional. The secondary type of the database if it is a secondary.') +param secondaryType 'Geo' | 'Named' | 'Standby'? @description('Optional. The time that the database was deleted when restoring a deleted database.') -param sourceDatabaseDeletionDate string = '' +param sourceDatabaseDeletionDate string? -@description('Optional. Resource ID of backup if createMode set to RestoreLongTermRetentionBackup.') -param recoveryServicesRecoveryPointResourceId string = '' +@description('Optional. The resource identifier of the source database associated with create operation of this database.') +param sourceDatabaseResourceId string? -@description('Optional. Point in time (ISO8601 format) of the source database to restore when createMode set to Restore or PointInTimeRestore.') -param restorePointInTime string = '' +@description('Optional. The resource identifier of the source associated with the create operation of this database.') +param sourceResourceId string? -@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 the database uses free monthly limits. Allowed on one database in a subscription.') +param useFreeLimit bool? -@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. Whether or not this database is zone redundant.') +param zoneRedundant bool = true -@description('Optional. Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur.') -param maintenanceConfigurationId string? +// END OF DATABASE PROPERTIES + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingFullType[]? @description('Optional. The short term backup retention policy to create for the database.') -param backupShortTermRetentionPolicy object = {} +param backupShortTermRetentionPolicy shortTermBackupRetentionPolicyType? @description('Optional. The long term backup retention policy to create for the database.') -param backupLongTermRetentionPolicy object = {} - -// 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 != null) - ? { - capacity: skuCapacity - } - : !empty(skuFamily) - ? { - family: skuFamily - } - : !empty(skuSize) - ? { - size: skuSize - } - : {} -) +param backupLongTermRetentionPolicy longTermBackupRetentionPolicyType? resource server 'Microsoft.Sql/servers@2023-08-01-preview' existing = { name: serverName @@ -151,30 +154,43 @@ resource database 'Microsoft.Sql/servers/databases@2023-08-01-preview' = { parent: server location: location tags: tags + sku: sku properties: { - preferredEnclaveType: !empty(preferredEnclaveType) ? preferredEnclaveType : null - collation: collation - maxSizeBytes: maxSizeBytes - sampleName: sampleName - zoneRedundant: zoneRedundant - licenseType: licenseType - readScale: readScale - minCapacity: !empty(minCapacity) ? json(minCapacity) : 0 // The json() function is used to allow specifying a decimal value. autoPauseDelay: autoPauseDelay + availabilityZone: availabilityZone + catalogCollation: catalogCollation + collation: collation + createMode: createMode + elasticPoolId: elasticPoolResourceId + encryptionProtector: encryptionProtector + encryptionProtectorAutoRotation: encryptionProtectorAutoRotation + federatedClientId: federatedClientId + freeLimitExhaustionBehavior: freeLimitExhaustionBehavior highAvailabilityReplicaCount: highAvailabilityReplicaCount - requestedBackupStorageRedundancy: any(requestedBackupStorageRedundancy) isLedgerOn: isLedgerOn + licenseType: licenseType + longTermRetentionBackupResourceId: longTermRetentionBackupResourceId maintenanceConfigurationId: maintenanceConfigurationId - elasticPoolId: elasticPoolId - createMode: createMode - sourceDatabaseId: !empty(sourceDatabaseResourceId) ? sourceDatabaseResourceId : null - sourceDatabaseDeletionDate: !empty(sourceDatabaseDeletionDate) ? sourceDatabaseDeletionDate : null - recoveryServicesRecoveryPointId: !empty(recoveryServicesRecoveryPointResourceId) - ? recoveryServicesRecoveryPointResourceId - : null - restorePointInTime: !empty(restorePointInTime) ? restorePointInTime : null + manualCutover: manualCutover + maxSizeBytes: maxSizeBytes + // The json() function is used to allow specifying a decimal value. + minCapacity: !empty(minCapacity) ? json(minCapacity) : 0 + performCutover: performCutover + preferredEnclaveType: preferredEnclaveType + readScale: readScale + recoverableDatabaseId: recoverableDatabaseResourceId + recoveryServicesRecoveryPointId: recoveryServicesRecoveryPointResourceId + requestedBackupStorageRedundancy: requestedBackupStorageRedundancy + restorableDroppedDatabaseId: restorableDroppedDatabaseResourceId + restorePointInTime: restorePointInTime + sampleName: sampleName + secondaryType: secondaryType + sourceDatabaseDeletionDate: sourceDatabaseDeletionDate + sourceDatabaseId: sourceDatabaseResourceId + sourceResourceId: sourceResourceId + useFreeLimit: useFreeLimit + zoneRedundant: zoneRedundant } - sku: skuVar } resource database_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ @@ -206,28 +222,34 @@ resource database_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021 } ] -module database_backupShortTermRetentionPolicy 'backup-short-term-retention-policy/main.bicep' = { +module database_backupShortTermRetentionPolicy 'backup-short-term-retention-policy/main.bicep' = if (!empty(backupShortTermRetentionPolicy)) { name: '${uniqueString(deployment().name, location)}-${name}-shBakRetPol' params: { serverName: serverName databaseName: database.name - diffBackupIntervalInHours: backupShortTermRetentionPolicy.?diffBackupIntervalInHours ?? 24 - retentionDays: backupShortTermRetentionPolicy.?retentionDays ?? 7 + diffBackupIntervalInHours: backupShortTermRetentionPolicy.?diffBackupIntervalInHours + retentionDays: backupShortTermRetentionPolicy.?retentionDays } } -module database_backupLongTermRetentionPolicy 'backup-long-term-retention-policy/main.bicep' = { +module database_backupLongTermRetentionPolicy 'backup-long-term-retention-policy/main.bicep' = if (!empty(backupLongTermRetentionPolicy)) { name: '${uniqueString(deployment().name, location)}-${name}-lgBakRetPol' params: { serverName: serverName databaseName: database.name - weeklyRetention: backupLongTermRetentionPolicy.?weeklyRetention ?? '' - monthlyRetention: backupLongTermRetentionPolicy.?monthlyRetention ?? '' - yearlyRetention: backupLongTermRetentionPolicy.?yearlyRetention ?? '' - weekOfYear: backupLongTermRetentionPolicy.?weekOfYear ?? 1 + backupStorageAccessTier: backupLongTermRetentionPolicy.?backupStorageAccessTier + makeBackupsImmutable: backupLongTermRetentionPolicy.?makeBackupsImmutable + weeklyRetention: backupLongTermRetentionPolicy.?weeklyRetention + monthlyRetention: backupLongTermRetentionPolicy.?monthlyRetention + yearlyRetention: backupLongTermRetentionPolicy.?yearlyRetention + weekOfYear: backupLongTermRetentionPolicy.?weekOfYear } } +// =============== // +// Outputs // +// =============== // + @description('The name of the deployed database.') output name string = database.name @@ -244,46 +266,53 @@ output location string = database.location // Definitions // // =============== // -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? +@export() +@description('The database SKU.') +type databaseSkuType = { + @description('Optional. The capacity of the particular SKU.') + capacity: int? - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? + @description('Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here.') + family: string? - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? + @description('Required. The name of the SKU, typically, a letter + Number code, e.g. P3.') + name: string - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? + @description('Optional. Size of the particular SKU.') + size: string? - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string + @description('Optional. The tier or edition of the particular SKU, e.g. Basic, Premium.') + tier: string? +} - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? +@export() +@description('The short-term backup retention policy for the database.') +type shortTermBackupRetentionPolicyType = { + @description('Optional. Differential backup interval in hours. For Hyperscale tiers this value will be ignored.') + diffBackupIntervalInHours: int? - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? + @description('Optional. Point-in-time retention in days.') + retentionDays: int? +} - @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.') - workspaceResourceId: string? +@export() +@description('The long-term backup retention policy for the database.') +type longTermBackupRetentionPolicyType = { + @description('Optional. The BackupStorageAccessTier for the LTR backups.') + backupStorageAccessTier: 'Archive' | 'Hot'? - @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.') - storageAccountResourceId: string? + @description('Optional. The setting whether to make LTR backups immutable.') + makeBackupsImmutable: bool? - @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.') - eventHubAuthorizationRuleResourceId: string? + @description('Optional. Monthly retention in ISO 8601 duration format.') + monthlyRetention: 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.') - eventHubName: string? + @description('Optional. Weekly retention in ISO 8601 duration format.') + weeklyRetention: string? - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? + @description('Optional. Week of year backup to keep for yearly retention.') + weekOfYear: int? + + @description('Optional. Yearly retention in ISO 8601 duration format.') + yearlyRetention: string? +} diff --git a/avm/res/sql/server/database/main.json b/avm/res/sql/server/database/main.json index 4be7b1af7f..1e9d3badae 100644 --- a/avm/res/sql/server/database/main.json +++ b/avm/res/sql/server/database/main.json @@ -5,133 +5,256 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "18021918128213514276" + "version": "0.30.23.60470", + "templateHash": "18018827030977470456" }, "name": "SQL Server Database", "description": "This module deploys an Azure SQL Server Database.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "databaseSkuType": { + "type": "object", + "properties": { + "capacity": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The capacity of the particular SKU." + } + }, + "family": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SKU, typically, a letter + Number code, e.g. P3." + } + }, + "size": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Size of the particular SKU." + } + }, + "tier": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tier or edition of the particular SKU, e.g. Basic, Premium." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The database SKU." + } + }, + "shortTermBackupRetentionPolicyType": { + "type": "object", + "properties": { + "diffBackupIntervalInHours": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Differential backup interval in hours. For Hyperscale tiers this value will be ignored." + } + }, + "retentionDays": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Point-in-time retention in days." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The short-term backup retention policy for the database." + } + }, + "longTermBackupRetentionPolicyType": { + "type": "object", + "properties": { + "backupStorageAccessTier": { + "type": "string", + "allowedValues": [ + "Archive", + "Hot" + ], + "nullable": true, + "metadata": { + "description": "Optional. The BackupStorageAccessTier for the LTR backups." + } + }, + "makeBackupsImmutable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The setting whether to make LTR backups immutable." + } + }, + "monthlyRetention": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Monthly retention in ISO 8601 duration format." + } + }, + "weeklyRetention": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Weekly retention in ISO 8601 duration format." + } + }, + "weekOfYear": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Week of year backup to keep for yearly retention." + } + }, + "yearlyRetention": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Yearly retention in ISO 8601 duration format." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The long-term backup retention policy for the database." + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." } }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -147,237 +270,333 @@ "description": "Conditional. The name of the parent SQL Server. Required if the template is used in a standalone deployment." } }, - "collation": { - "type": "string", - "defaultValue": "SQL_Latin1_General_CP1_CI_AS", + "sku": { + "$ref": "#/definitions/databaseSkuType", + "defaultValue": { + "name": "GP_Gen5_2", + "tier": "GeneralPurpose" + }, "metadata": { - "description": "Optional. The collation of the database." + "description": "Optional. The database SKU." + } + }, + "autoPauseDelay": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled." } }, - "skuTier": { + "availabilityZone": { "type": "string", - "defaultValue": "GeneralPurpose", + "allowedValues": [ + "1", + "2", + "3", + "NoPreference" + ], + "defaultValue": "NoPreference", "metadata": { - "description": "Optional. The skuTier or edition of the particular SKU." + "description": "Optional. Specifies the availability zone the database is pinned to." } }, - "skuName": { + "catalogCollation": { "type": "string", - "defaultValue": "GP_Gen5_2", + "defaultValue": "DATABASE_DEFAULT", "metadata": { - "description": "Optional. The name of the SKU." + "description": "Optional. Collation of the metadata catalog." } }, - "skuCapacity": { - "type": "int", - "nullable": true, + "collation": { + "type": "string", + "defaultValue": "SQL_Latin1_General_CP1_CI_AS", "metadata": { - "description": "Optional. Capacity of the particular SKU." + "description": "Optional. The collation of the database." } }, - "preferredEnclaveType": { + "createMode": { "type": "string", - "defaultValue": "", "allowedValues": [ - "", + "Copy", "Default", - "VBS" + "OnlineSecondary", + "PointInTimeRestore", + "Recovery", + "Restore", + "RestoreExternalBackup", + "RestoreExternalBackupSecondary", + "RestoreLongTermRetentionBackup", + "Secondary" ], + "defaultValue": "Default", "metadata": { - "description": "Optional. Type of enclave requested on the database i.e. Default or VBS enclaves." + "description": "Optional. Specifies the mode of database creation." } }, - "skuFamily": { + "elasticPoolResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { - "description": "Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here." + "description": "Optional. The resource ID of the elastic pool containing this database." } }, - "skuSize": { + "encryptionProtector": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { - "description": "Optional. Size of the particular SKU." + "description": "Optional. The azure key vault URI of the database if it's configured with per Database Customer Managed Keys." } }, - "maxSizeBytes": { - "type": "int", - "defaultValue": 34359738368, + "encryptionProtectorAutoRotation": { + "type": "bool", + "nullable": true, "metadata": { - "description": "Optional. The max size of the database expressed in bytes." + "description": "Optional. The flag to enable or disable auto rotation of database encryption protector AKV key." } }, - "sampleName": { + "federatedClientId": { "type": "string", - "defaultValue": "", + "nullable": true, + "minLength": 36, + "maxLength": 36, "metadata": { - "description": "Optional. The name of the sample schema to apply when creating this database." + "description": "Optional. The Client id used for cross tenant per database CMK scenario." } }, - "zoneRedundant": { + "freeLimitExhaustionBehavior": { + "type": "string", + "allowedValues": [ + "AutoPause", + "BillOverUsage" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the behavior when monthly free limits are exhausted for the free database." + } + }, + "highAvailabilityReplicaCount": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. The number of readonly secondary replicas associated with the database." + } + }, + "isLedgerOn": { "type": "bool", - "defaultValue": true, + "defaultValue": false, "metadata": { - "description": "Optional. Whether or not this database is zone redundant." + "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." } }, "licenseType": { "type": "string", - "defaultValue": "", + "allowedValues": [ + "BasePrice", + "LicenseIncluded" + ], + "nullable": true, "metadata": { "description": "Optional. The license type to apply for this database." } }, - "readScale": { + "longTermRetentionBackupResourceId": { "type": "string", - "defaultValue": "Disabled", - "allowedValues": [ - "Enabled", - "Disabled" - ], + "nullable": true, "metadata": { - "description": "Optional. The state of read-only routing." + "description": "Optional. The resource identifier of the long term retention backup associated with create operation of this database." } }, - "highAvailabilityReplicaCount": { + "maintenanceConfigurationId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur." + } + }, + "manualCutover": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether or not customer controlled manual cutover needs to be done during Update Database operation to Hyperscale tier." + } + }, + "maxSizeBytes": { "type": "int", - "defaultValue": 0, + "defaultValue": 34359738368, "metadata": { - "description": "Optional. The number of readonly secondary replicas associated with the database." + "description": "Optional. The max size of the database expressed in bytes." } }, "minCapacity": { "type": "string", - "defaultValue": "", + "defaultValue": "0", "metadata": { "description": "Optional. Minimal capacity that database will always have allocated." } }, - "autoPauseDelay": { - "type": "int", - "defaultValue": 0, + "performCutover": { + "type": "bool", + "nullable": true, "metadata": { - "description": "Optional. Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled." + "description": "Optional. To trigger customer controlled manual cutover during the wait state while Scaling operation is in progress." } }, - "tags": { - "type": "object", + "preferredEnclaveType": { + "type": "string", + "allowedValues": [ + "Default", + "VBS" + ], "nullable": true, "metadata": { - "description": "Optional. Tags of the resource." + "description": "Optional. Type of enclave requested on the database i.e. Default or VBS enclaves." } }, - "elasticPoolId": { + "readScale": { "type": "string", - "defaultValue": "", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "defaultValue": "Disabled", "metadata": { - "description": "Optional. The resource ID of the elastic pool containing this database." + "description": "Optional. The state of read-only routing." } }, - "location": { + "recoverableDatabaseResourceId": { "type": "string", - "defaultValue": "[resourceGroup().location]", + "nullable": true, "metadata": { - "description": "Optional. Location for all resources." + "description": "Optional. The resource identifier of the recoverable database associated with create operation of this database." } }, - "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "recoveryServicesRecoveryPointResourceId": { + "type": "string", + "nullable": true, "metadata": { - "description": "Optional. The diagnostic settings of the service." + "description": "Optional. The resource identifier of the recovery point associated with create operation of this database." } }, - "createMode": { + "requestedBackupStorageRedundancy": { "type": "string", - "defaultValue": "Default", "allowedValues": [ - "Default", - "Copy", - "OnlineSecondary", - "PointInTimeRestore", - "Recovery", - "Restore", - "RestoreLongTermRetentionBackup", - "Secondary" + "Geo", + "GeoZone", + "Local", + "Zone" ], + "defaultValue": "Local", "metadata": { - "description": "Optional. Specifies the mode of database creation." + "description": "Optional. The storage account type to be used to store backups for this database." } }, - "sourceDatabaseResourceId": { + "restorableDroppedDatabaseResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource identifier of the restorable dropped database associated with create operation of this database." + } + }, + "restorePointInTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Point in time (ISO8601 format) of the source database to restore when createMode set to Restore or PointInTimeRestore." + } + }, + "sampleName": { "type": "string", "defaultValue": "", "metadata": { - "description": "Optional. Resource ID of database if createMode set to Copy, Secondary, PointInTimeRestore, Recovery or Restore." + "description": "Optional. The name of the sample schema to apply when creating this database." + } + }, + "secondaryType": { + "type": "string", + "allowedValues": [ + "Geo", + "Named", + "Standby" + ], + "nullable": true, + "metadata": { + "description": "Optional. The secondary type of the database if it is a secondary." } }, "sourceDatabaseDeletionDate": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The time that the database was deleted when restoring a deleted database." } }, - "recoveryServicesRecoveryPointResourceId": { + "sourceDatabaseResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { - "description": "Optional. Resource ID of backup if createMode set to RestoreLongTermRetentionBackup." + "description": "Optional. The resource identifier of the source database associated with create operation of this database." } }, - "restorePointInTime": { + "sourceResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { - "description": "Optional. Point in time (ISO8601 format) of the source database to restore when createMode set to Restore or PointInTimeRestore." + "description": "Optional. The resource identifier of the source associated with the create operation of this database." } }, - "requestedBackupStorageRedundancy": { - "type": "string", - "defaultValue": "", - "allowedValues": [ - "Geo", - "Local", - "Zone", - "" - ], + "useFreeLimit": { + "type": "bool", + "nullable": true, "metadata": { - "description": "Optional. The storage account type to be used to store backups for this database." + "description": "Optional. Whether or not the database uses free monthly limits. Allowed on one database in a subscription." } }, - "isLedgerOn": { + "zoneRedundant": { "type": "bool", - "defaultValue": false, + "defaultValue": true, "metadata": { - "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." + "description": "Optional. Whether or not this database is zone redundant." } }, - "maintenanceConfigurationId": { + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "location": { "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "diagnosticSettings": { + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, "nullable": true, "metadata": { - "description": "Optional. Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur." + "description": "Optional. The diagnostic settings of the service." } }, "backupShortTermRetentionPolicy": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/shortTermBackupRetentionPolicyType", + "nullable": true, "metadata": { "description": "Optional. The short term backup retention policy to create for the database." } }, "backupLongTermRetentionPolicy": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/longTermBackupRetentionPolicyType", + "nullable": true, "metadata": { "description": "Optional. The long term backup retention policy to create for the database." } } }, - "variables": { - "skuVar": "[union(createObject('name', parameters('skuName'), 'tier', parameters('skuTier')), if(not(equals(parameters('skuCapacity'), null())), createObject('capacity', parameters('skuCapacity')), if(not(empty(parameters('skuFamily'))), createObject('family', parameters('skuFamily')), if(not(empty(parameters('skuSize'))), createObject('size', parameters('skuSize')), createObject()))))]" - }, "resources": { "server": { "existing": true, @@ -391,28 +610,42 @@ "name": "[format('{0}/{1}', parameters('serverName'), parameters('name'))]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", + "sku": "[parameters('sku')]", "properties": { - "preferredEnclaveType": "[if(not(empty(parameters('preferredEnclaveType'))), parameters('preferredEnclaveType'), null())]", - "collation": "[parameters('collation')]", - "maxSizeBytes": "[parameters('maxSizeBytes')]", - "sampleName": "[parameters('sampleName')]", - "zoneRedundant": "[parameters('zoneRedundant')]", - "licenseType": "[parameters('licenseType')]", - "readScale": "[parameters('readScale')]", - "minCapacity": "[if(not(empty(parameters('minCapacity'))), json(parameters('minCapacity')), 0)]", "autoPauseDelay": "[parameters('autoPauseDelay')]", + "availabilityZone": "[parameters('availabilityZone')]", + "catalogCollation": "[parameters('catalogCollation')]", + "collation": "[parameters('collation')]", + "createMode": "[parameters('createMode')]", + "elasticPoolId": "[parameters('elasticPoolResourceId')]", + "encryptionProtector": "[parameters('encryptionProtector')]", + "encryptionProtectorAutoRotation": "[parameters('encryptionProtectorAutoRotation')]", + "federatedClientId": "[parameters('federatedClientId')]", + "freeLimitExhaustionBehavior": "[parameters('freeLimitExhaustionBehavior')]", "highAvailabilityReplicaCount": "[parameters('highAvailabilityReplicaCount')]", - "requestedBackupStorageRedundancy": "[parameters('requestedBackupStorageRedundancy')]", "isLedgerOn": "[parameters('isLedgerOn')]", + "licenseType": "[parameters('licenseType')]", + "longTermRetentionBackupResourceId": "[parameters('longTermRetentionBackupResourceId')]", "maintenanceConfigurationId": "[parameters('maintenanceConfigurationId')]", - "elasticPoolId": "[parameters('elasticPoolId')]", - "createMode": "[parameters('createMode')]", - "sourceDatabaseId": "[if(not(empty(parameters('sourceDatabaseResourceId'))), parameters('sourceDatabaseResourceId'), null())]", - "sourceDatabaseDeletionDate": "[if(not(empty(parameters('sourceDatabaseDeletionDate'))), parameters('sourceDatabaseDeletionDate'), null())]", - "recoveryServicesRecoveryPointId": "[if(not(empty(parameters('recoveryServicesRecoveryPointResourceId'))), parameters('recoveryServicesRecoveryPointResourceId'), null())]", - "restorePointInTime": "[if(not(empty(parameters('restorePointInTime'))), parameters('restorePointInTime'), null())]" + "manualCutover": "[parameters('manualCutover')]", + "maxSizeBytes": "[parameters('maxSizeBytes')]", + "minCapacity": "[if(not(empty(parameters('minCapacity'))), json(parameters('minCapacity')), 0)]", + "performCutover": "[parameters('performCutover')]", + "preferredEnclaveType": "[parameters('preferredEnclaveType')]", + "readScale": "[parameters('readScale')]", + "recoverableDatabaseId": "[parameters('recoverableDatabaseResourceId')]", + "recoveryServicesRecoveryPointId": "[parameters('recoveryServicesRecoveryPointResourceId')]", + "requestedBackupStorageRedundancy": "[parameters('requestedBackupStorageRedundancy')]", + "restorableDroppedDatabaseId": "[parameters('restorableDroppedDatabaseResourceId')]", + "restorePointInTime": "[parameters('restorePointInTime')]", + "sampleName": "[parameters('sampleName')]", + "secondaryType": "[parameters('secondaryType')]", + "sourceDatabaseDeletionDate": "[parameters('sourceDatabaseDeletionDate')]", + "sourceDatabaseId": "[parameters('sourceDatabaseResourceId')]", + "sourceResourceId": "[parameters('sourceResourceId')]", + "useFreeLimit": "[parameters('useFreeLimit')]", + "zoneRedundant": "[parameters('zoneRedundant')]" }, - "sku": "[variables('skuVar')]", "dependsOn": [ "server" ] @@ -459,6 +692,7 @@ ] }, "database_backupShortTermRetentionPolicy": { + "condition": "[not(empty(parameters('backupShortTermRetentionPolicy')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-{1}-shBakRetPol', uniqueString(deployment().name, parameters('location')), parameters('name'))]", @@ -475,10 +709,10 @@ "value": "[parameters('name')]" }, "diffBackupIntervalInHours": { - "value": "[coalesce(tryGet(parameters('backupShortTermRetentionPolicy'), 'diffBackupIntervalInHours'), 24)]" + "value": "[tryGet(parameters('backupShortTermRetentionPolicy'), 'diffBackupIntervalInHours')]" }, "retentionDays": { - "value": "[coalesce(tryGet(parameters('backupShortTermRetentionPolicy'), 'retentionDays'), 7)]" + "value": "[tryGet(parameters('backupShortTermRetentionPolicy'), 'retentionDays')]" } }, "template": { @@ -487,8 +721,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8635162595153731245" + "version": "0.30.23.60470", + "templateHash": "14890409200962565555" }, "name": "Azure SQL Server Database Short Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Short-Term Backup Retention Policy.", @@ -511,7 +745,7 @@ "type": "int", "defaultValue": 24, "metadata": { - "description": "Optional. Differential backup interval in hours." + "description": "Optional. Differential backup interval in hours. For Hyperscal tiers this value will be ignored." } }, "retentionDays": { @@ -528,7 +762,7 @@ "apiVersion": "2023-08-01-preview", "name": "[format('{0}/{1}/{2}', parameters('serverName'), parameters('databaseName'), 'default')]", "properties": { - "diffBackupIntervalInHours": "[parameters('diffBackupIntervalInHours')]", + "diffBackupIntervalInHours": "[if(equals(reference(resourceId('Microsoft.Sql/servers/databases', parameters('serverName'), parameters('databaseName')), '2023-08-01-preview', 'full').sku.tier, 'Hyperscale'), null(), parameters('diffBackupIntervalInHours'))]", "retentionDays": "[parameters('retentionDays')]" } } @@ -563,6 +797,7 @@ ] }, "database_backupLongTermRetentionPolicy": { + "condition": "[not(empty(parameters('backupLongTermRetentionPolicy')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-{1}-lgBakRetPol', uniqueString(deployment().name, parameters('location')), parameters('name'))]", @@ -578,27 +813,34 @@ "databaseName": { "value": "[parameters('name')]" }, + "backupStorageAccessTier": { + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'backupStorageAccessTier')]" + }, + "makeBackupsImmutable": { + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'makeBackupsImmutable')]" + }, "weeklyRetention": { - "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'weeklyRetention'), '')]" + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'weeklyRetention')]" }, "monthlyRetention": { - "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'monthlyRetention'), '')]" + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'monthlyRetention')]" }, "yearlyRetention": { - "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'yearlyRetention'), '')]" + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'yearlyRetention')]" }, "weekOfYear": { - "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'weekOfYear'), 1)]" + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'weekOfYear')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2778016138108001251" + "version": "0.30.23.60470", + "templateHash": "841731129374883266" }, "name": "SQL Server Database Long Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Long-Term Backup Retention Policy.", @@ -617,16 +859,34 @@ "description": "Required. The name of the parent database." } }, - "weeklyRetention": { + "backupStorageAccessTier": { "type": "string", - "defaultValue": "", + "allowedValues": [ + "Archive", + "Hot" + ], + "nullable": true, "metadata": { - "description": "Optional. Monthly retention in ISO 8601 duration format." + "description": "Optional. The BackupStorageAccessTier for the LTR backups." + } + }, + "makeBackupsImmutable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The setting whether to make LTR backups immutable." } }, "monthlyRetention": { "type": "string", - "defaultValue": "", + "nullable": true, + "metadata": { + "description": "Optional. Monthly retention in ISO 8601 duration format." + } + }, + "weeklyRetention": { + "type": "string", + "nullable": true, "metadata": { "description": "Optional. Weekly retention in ISO 8601 duration format." } @@ -640,25 +900,45 @@ }, "yearlyRetention": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Yearly retention in ISO 8601 duration format." } } }, - "resources": [ - { - "type": "Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies", + "resources": { + "server::database": { + "existing": true, + "type": "Microsoft.Sql/servers/databases", "apiVersion": "2023-08-01-preview", + "name": "[format('{0}/{1}', parameters('serverName'), parameters('databaseName'))]", + "dependsOn": [ + "server" + ] + }, + "server": { + "existing": true, + "type": "Microsoft.Sql/servers", + "apiVersion": "2023-08-01-preview", + "name": "[parameters('serverName')]" + }, + "backupLongTermRetentionPolicy": { + "type": "Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies", + "apiVersion": "2023-05-01-preview", "name": "[format('{0}/{1}/{2}', parameters('serverName'), parameters('databaseName'), 'default')]", "properties": { + "backupStorageAccessTier": "[parameters('backupStorageAccessTier')]", + "makeBackupsImmutable": "[parameters('makeBackupsImmutable')]", "monthlyRetention": "[parameters('monthlyRetention')]", "weeklyRetention": "[parameters('weeklyRetention')]", "weekOfYear": "[parameters('weekOfYear')]", "yearlyRetention": "[parameters('yearlyRetention')]" - } + }, + "dependsOn": [ + "server::database" + ] } - ], + }, "outputs": { "resourceGroupName": { "type": "string", diff --git a/avm/res/sql/server/elastic-pool/README.md b/avm/res/sql/server/elastic-pool/README.md index ef598e5fa3..33336196b5 100644 --- a/avm/res/sql/server/elastic-pool/README.md +++ b/avm/res/sql/server/elastic-pool/README.md @@ -32,17 +32,17 @@ This module deploys an Azure SQL Server Elastic Pool. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`databaseMaxCapacity`](#parameter-databasemaxcapacity) | int | The maximum capacity any one database can consume. | -| [`databaseMinCapacity`](#parameter-databasemincapacity) | int | The minimum capacity all databases are guaranteed. | +| [`autoPauseDelay`](#parameter-autopausedelay) | int | Time in minutes after which elastic pool is automatically paused. A value of -1 means that automatic pause is disabled. | +| [`availabilityZone`](#parameter-availabilityzone) | string | Specifies the availability zone the pool's primary replica is pinned to. | | [`highAvailabilityReplicaCount`](#parameter-highavailabilityreplicacount) | int | The number of secondary replicas associated with the elastic pool that are used to provide high availability. Applicable only to Hyperscale elastic pools. | | [`licenseType`](#parameter-licensetype) | string | The license type to apply for this elastic pool. | | [`location`](#parameter-location) | string | Location for all resources. | | [`maintenanceConfigurationId`](#parameter-maintenanceconfigurationid) | string | Maintenance configuration resource ID assigned to the elastic pool. This configuration defines the period when the maintenance updates will will occur. | | [`maxSizeBytes`](#parameter-maxsizebytes) | int | The storage limit for the database elastic pool in bytes. | | [`minCapacity`](#parameter-mincapacity) | int | Minimal capacity that serverless pool will not shrink below, if not paused. | -| [`skuCapacity`](#parameter-skucapacity) | int | Capacity of the particular SKU. | -| [`skuName`](#parameter-skuname) | string | The name of the SKU, typically, a letter + Number code, e.g. P3. | -| [`skuTier`](#parameter-skutier) | string | The tier or edition of the particular SKU, e.g. Basic, Premium. | +| [`perDatabaseSettings`](#parameter-perdatabasesettings) | object | The per database settings for the elastic pool. | +| [`preferredEnclaveType`](#parameter-preferredenclavetype) | string | Type of enclave requested on the elastic pool. | +| [`sku`](#parameter-sku) | object | The elastic pool SKU. | | [`tags`](#parameter-tags) | object | Tags of the resource. | | [`zoneRedundant`](#parameter-zoneredundant) | bool | Whether or not this elastic pool is zone redundant, which means the replicas of this elastic pool will be spread across multiple availability zones. | @@ -60,21 +60,30 @@ The name of the parent SQL Server. Required if the template is used in a standal - Required: Yes - Type: string -### Parameter: `databaseMaxCapacity` +### Parameter: `autoPauseDelay` -The maximum capacity any one database can consume. +Time in minutes after which elastic pool is automatically paused. A value of -1 means that automatic pause is disabled. - Required: No - Type: int -- Default: `2` +- Default: `-1` -### Parameter: `databaseMinCapacity` +### Parameter: `availabilityZone` -The minimum capacity all databases are guaranteed. +Specifies the availability zone the pool's primary replica is pinned to. - Required: No -- Type: int -- Default: `0` +- Type: string +- Default: `'NoPreference'` +- Allowed: + ```Bicep + [ + '1' + '2' + '3' + 'NoPreference' + ] + ``` ### Parameter: `highAvailabilityReplicaCount` @@ -128,29 +137,151 @@ Minimal capacity that serverless pool will not shrink below, if not paused. - Required: No - Type: int -### Parameter: `skuCapacity` +### Parameter: `perDatabaseSettings` -Capacity of the particular SKU. +The per database settings for the elastic pool. + +- Required: No +- Type: object +- Default: + ```Bicep + { + autoPauseDelay: -1 + maxCapacity: '2' + minCapacity: '0' + } + ``` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`maxCapacity`](#parameter-perdatabasesettingsmaxcapacity) | string | The maximum capacity any one database can consume. Examples: '0.5', '2'. | +| [`minCapacity`](#parameter-perdatabasesettingsmincapacity) | string | The minimum capacity all databases are guaranteed. Examples: '0.5', '1'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoPauseDelay`](#parameter-perdatabasesettingsautopausedelay) | int | Auto Pause Delay for per database within pool. | + +### Parameter: `perDatabaseSettings.maxCapacity` + +The maximum capacity any one database can consume. Examples: '0.5', '2'. + +- Required: Yes +- Type: string + +### Parameter: `perDatabaseSettings.minCapacity` + +The minimum capacity all databases are guaranteed. Examples: '0.5', '1'. + +- Required: Yes +- Type: string + +### Parameter: `perDatabaseSettings.autoPauseDelay` + +Auto Pause Delay for per database within pool. - Required: No - Type: int -- Default: `2` -### Parameter: `skuName` +### Parameter: `preferredEnclaveType` + +Type of enclave requested on the elastic pool. + +- Required: No +- Type: string +- Default: `'Default'` +- Allowed: + ```Bicep + [ + 'Default' + 'VBS' + ] + ``` + +### Parameter: `sku` + +The elastic pool SKU. + +- Required: No +- Type: object +- Default: + ```Bicep + { + capacity: 2 + name: 'GP_Gen5' + tier: 'GeneralPurpose' + } + ``` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-skuname) | string | The name of the SKU, typically, a letter + Number code, e.g. P3. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacity`](#parameter-skucapacity) | int | The capacity of the particular SKU. | +| [`family`](#parameter-skufamily) | string | If the service has different generations of hardware, for the same SKU, then that can be captured here. | +| [`size`](#parameter-skusize) | string | Size of the particular SKU. | +| [`tier`](#parameter-skutier) | string | The tier or edition of the particular SKU, e.g. Basic, Premium. | + +### Parameter: `sku.name` The name of the SKU, typically, a letter + Number code, e.g. P3. +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'BasicPool' + 'BC_DC' + 'BC_Gen5' + 'GP_DC' + 'GP_FSv2' + 'GP_Gen5' + 'HS_Gen5' + 'HS_MOPRMS' + 'HS_PRMS' + 'PremiumPool' + 'ServerlessPool' + 'StandardPool' + ] + ``` + +### Parameter: `sku.capacity` + +The capacity of the particular SKU. + +- Required: No +- Type: int + +### Parameter: `sku.family` + +If the service has different generations of hardware, for the same SKU, then that can be captured here. + +- Required: No +- Type: string + +### Parameter: `sku.size` + +Size of the particular SKU. + - Required: No - Type: string -- Default: `'GP_Gen5'` -### Parameter: `skuTier` +### Parameter: `sku.tier` The tier or edition of the particular SKU, e.g. Basic, Premium. - Required: No - Type: string -- Default: `'GeneralPurpose'` ### Parameter: `tags` diff --git a/avm/res/sql/server/elastic-pool/main.bicep b/avm/res/sql/server/elastic-pool/main.bicep index df5d5510ea..1fb87683b2 100644 --- a/avm/res/sql/server/elastic-pool/main.bicep +++ b/avm/res/sql/server/elastic-pool/main.bicep @@ -14,14 +14,18 @@ param tags object? @description('Optional. Location for all resources.') param location string = resourceGroup().location -@description('Optional. Capacity of the particular SKU.') -param skuCapacity int = 2 +@description('Optional. The elastic pool SKU.') +param sku elasticPoolSkuType = { + capacity: 2 + name: 'GP_Gen5' + tier: 'GeneralPurpose' +} -@description('Optional. The name of the SKU, typically, a letter + Number code, e.g. P3.') -param skuName string = 'GP_Gen5' +@description('Optional. Time in minutes after which elastic pool is automatically paused. A value of -1 means that automatic pause is disabled.') +param autoPauseDelay int = -1 -@description('Optional. The tier or edition of the particular SKU, e.g. Basic, Premium.') -param skuTier string = 'GeneralPurpose' +@description('Optional. Specifies the availability zone the pool\'s primary replica is pinned to.') +param availabilityZone '1' | '2' | '3' | 'NoPreference' = 'NoPreference' @description('Optional. The number of secondary replicas associated with the elastic pool that are used to provide high availability. Applicable only to Hyperscale elastic pools.') param highAvailabilityReplicaCount int? @@ -42,11 +46,15 @@ param maxSizeBytes int = 34359738368 @description('Optional. Minimal capacity that serverless pool will not shrink below, if not paused.') param minCapacity int? -@description('Optional. The maximum capacity any one database can consume.') -param databaseMaxCapacity int = 2 +@description('Optional. The per database settings for the elastic pool.') +param perDatabaseSettings elasticPoolPerDatabaseSettingsType = { + autoPauseDelay: -1 + maxCapacity: '2' + minCapacity: '0' +} -@description('Optional. The minimum capacity all databases are guaranteed.') -param databaseMinCapacity int = 0 +@description('Optional. Type of enclave requested on the elastic pool.') +param preferredEnclaveType 'Default' | 'VBS' = 'Default' @description('Optional. Whether or not this elastic pool is zone redundant, which means the replicas of this elastic pool will be spread across multiple availability zones.') param zoneRedundant bool = true @@ -60,21 +68,24 @@ resource elasticPool 'Microsoft.Sql/servers/elasticPools@2023-08-01-preview' = { location: location parent: server tags: tags - sku: { - capacity: skuCapacity - name: skuName - tier: skuTier - } + sku: sku properties: { + autoPauseDelay: autoPauseDelay + availabilityZone: availabilityZone highAvailabilityReplicaCount: highAvailabilityReplicaCount licenseType: licenseType maintenanceConfigurationId: maintenanceConfigurationId maxSizeBytes: maxSizeBytes minCapacity: minCapacity - perDatabaseSettings: { - minCapacity: databaseMinCapacity - maxCapacity: databaseMaxCapacity - } + perDatabaseSettings: !empty(perDatabaseSettings) + ? { + autoPauseDelay: perDatabaseSettings.?autoPauseDelay + // To handle fractional values, we need to convert from string :( + maxCapacity: json(perDatabaseSettings.?maxCapacity) + minCapacity: json(perDatabaseSettings.?minCapacity) + } + : null + preferredEnclaveType: preferredEnclaveType zoneRedundant: zoneRedundant } } @@ -90,3 +101,52 @@ output resourceGroupName string = resourceGroup().name @description('The location the resource was deployed into.') output location string = elasticPool.location + +// =============== // +// Definitions // +// =============== // + +@export() +@description('The per database settings for the elastic pool.') +type elasticPoolPerDatabaseSettingsType = { + @description('Optional. Auto Pause Delay for per database within pool.') + autoPauseDelay: int? + + @description('Required. The maximum capacity any one database can consume. Examples: \'0.5\', \'2\'.') + maxCapacity: string + + // using string as minCapacity can be fractional + @description('Required. The minimum capacity all databases are guaranteed. Examples: \'0.5\', \'1\'.') + minCapacity: string +} + +@export() +@description('The elastic pool SKU.') +type elasticPoolSkuType = { + @description('Optional. The capacity of the particular SKU.') + capacity: int? + + @description('Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here.') + family: string? + + @description('Required. The name of the SKU, typically, a letter + Number code, e.g. P3.') + name: + | 'BasicPool' + | 'StandardPool' + | 'PremiumPool' + | 'GP_Gen5' + | 'GP_DC' + | 'GP_FSv2' + | 'BC_Gen5' + | 'BC_DC' + | 'HS_Gen5' + | 'HS_PRMS' + | 'HS_MOPRMS' + | 'ServerlessPool' + + @description('Optional. Size of the particular SKU.') + size: string? + + @description('Optional. The tier or edition of the particular SKU, e.g. Basic, Premium.') + tier: string? +} diff --git a/avm/res/sql/server/elastic-pool/main.json b/avm/res/sql/server/elastic-pool/main.json index 5acc2b0818..d74f427cbe 100644 --- a/avm/res/sql/server/elastic-pool/main.json +++ b/avm/res/sql/server/elastic-pool/main.json @@ -5,13 +5,100 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17774091526328280898" + "version": "0.30.23.60470", + "templateHash": "10024079638382167120" }, "name": "SQL Server Elastic Pool", "description": "This module deploys an Azure SQL Server Elastic Pool.", "owner": "Azure/module-maintainers" }, + "definitions": { + "elasticPoolPerDatabaseSettingsType": { + "type": "object", + "properties": { + "autoPauseDelay": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Auto Pause Delay for per database within pool." + } + }, + "maxCapacity": { + "type": "string", + "metadata": { + "description": "Required. The maximum capacity any one database can consume. Examples: '0.5', '2'." + } + }, + "minCapacity": { + "type": "string", + "metadata": { + "description": "Required. The minimum capacity all databases are guaranteed. Examples: '0.5', '1'." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The per database settings for the elastic pool." + } + }, + "elasticPoolSkuType": { + "type": "object", + "properties": { + "capacity": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The capacity of the particular SKU." + } + }, + "family": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here." + } + }, + "name": { + "type": "string", + "allowedValues": [ + "BC_DC", + "BC_Gen5", + "BasicPool", + "GP_DC", + "GP_FSv2", + "GP_Gen5", + "HS_Gen5", + "HS_MOPRMS", + "HS_PRMS", + "PremiumPool", + "ServerlessPool", + "StandardPool" + ], + "metadata": { + "description": "Required. The name of the SKU, typically, a letter + Number code, e.g. P3." + } + }, + "size": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Size of the particular SKU." + } + }, + "tier": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tier or edition of the particular SKU, e.g. Basic, Premium." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The elastic pool SKU." + } + } + }, "parameters": { "name": { "type": "string", @@ -39,25 +126,35 @@ "description": "Optional. Location for all resources." } }, - "skuCapacity": { - "type": "int", - "defaultValue": 2, + "sku": { + "$ref": "#/definitions/elasticPoolSkuType", + "defaultValue": { + "capacity": 2, + "name": "GP_Gen5", + "tier": "GeneralPurpose" + }, "metadata": { - "description": "Optional. Capacity of the particular SKU." + "description": "Optional. The elastic pool SKU." } }, - "skuName": { - "type": "string", - "defaultValue": "GP_Gen5", + "autoPauseDelay": { + "type": "int", + "defaultValue": -1, "metadata": { - "description": "Optional. The name of the SKU, typically, a letter + Number code, e.g. P3." + "description": "Optional. Time in minutes after which elastic pool is automatically paused. A value of -1 means that automatic pause is disabled." } }, - "skuTier": { + "availabilityZone": { "type": "string", - "defaultValue": "GeneralPurpose", + "allowedValues": [ + "1", + "2", + "3", + "NoPreference" + ], + "defaultValue": "NoPreference", "metadata": { - "description": "Optional. The tier or edition of the particular SKU, e.g. Basic, Premium." + "description": "Optional. Specifies the availability zone the pool's primary replica is pinned to." } }, "highAvailabilityReplicaCount": { @@ -99,18 +196,26 @@ "description": "Optional. Minimal capacity that serverless pool will not shrink below, if not paused." } }, - "databaseMaxCapacity": { - "type": "int", - "defaultValue": 2, + "perDatabaseSettings": { + "$ref": "#/definitions/elasticPoolPerDatabaseSettingsType", + "defaultValue": { + "autoPauseDelay": -1, + "maxCapacity": "2", + "minCapacity": "0" + }, "metadata": { - "description": "Optional. The maximum capacity any one database can consume." + "description": "Optional. The per database settings for the elastic pool." } }, - "databaseMinCapacity": { - "type": "int", - "defaultValue": 0, + "preferredEnclaveType": { + "type": "string", + "allowedValues": [ + "Default", + "VBS" + ], + "defaultValue": "Default", "metadata": { - "description": "Optional. The minimum capacity all databases are guaranteed." + "description": "Optional. Type of enclave requested on the elastic pool." } }, "zoneRedundant": { @@ -134,21 +239,17 @@ "name": "[format('{0}/{1}', parameters('serverName'), parameters('name'))]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", - "sku": { - "capacity": "[parameters('skuCapacity')]", - "name": "[parameters('skuName')]", - "tier": "[parameters('skuTier')]" - }, + "sku": "[parameters('sku')]", "properties": { + "autoPauseDelay": "[parameters('autoPauseDelay')]", + "availabilityZone": "[parameters('availabilityZone')]", "highAvailabilityReplicaCount": "[parameters('highAvailabilityReplicaCount')]", "licenseType": "[parameters('licenseType')]", "maintenanceConfigurationId": "[parameters('maintenanceConfigurationId')]", "maxSizeBytes": "[parameters('maxSizeBytes')]", "minCapacity": "[parameters('minCapacity')]", - "perDatabaseSettings": { - "minCapacity": "[parameters('databaseMinCapacity')]", - "maxCapacity": "[parameters('databaseMaxCapacity')]" - }, + "perDatabaseSettings": "[if(not(empty(parameters('perDatabaseSettings'))), createObject('autoPauseDelay', tryGet(parameters('perDatabaseSettings'), 'autoPauseDelay'), 'maxCapacity', json(tryGet(parameters('perDatabaseSettings'), 'maxCapacity')), 'minCapacity', json(tryGet(parameters('perDatabaseSettings'), 'minCapacity'))), null())]", + "preferredEnclaveType": "[parameters('preferredEnclaveType')]", "zoneRedundant": "[parameters('zoneRedundant')]" }, "dependsOn": [ diff --git a/avm/res/sql/server/encryption-protector/main.json b/avm/res/sql/server/encryption-protector/main.json index 8e8deb599e..2191d5c1ae 100644 --- a/avm/res/sql/server/encryption-protector/main.json +++ b/avm/res/sql/server/encryption-protector/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6914924378490463775" + "version": "0.30.23.60470", + "templateHash": "11473914706327458055" }, "name": "Azure SQL Server Encryption Protector", "description": "This module deploys an Azure SQL Server Encryption Protector.", diff --git a/avm/res/sql/server/firewall-rule/main.json b/avm/res/sql/server/firewall-rule/main.json index 006ddcd226..fb23b82744 100644 --- a/avm/res/sql/server/firewall-rule/main.json +++ b/avm/res/sql/server/firewall-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7779473510493338097" + "version": "0.30.23.60470", + "templateHash": "6449556555046717103" }, "name": "Azure SQL Server Firewall Rule", "description": "This module deploys an Azure SQL Server Firewall Rule.", diff --git a/avm/res/sql/server/key/main.json b/avm/res/sql/server/key/main.json index 78e43db8f4..78220cdf1f 100644 --- a/avm/res/sql/server/key/main.json +++ b/avm/res/sql/server/key/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5863771213375512760" + "version": "0.30.23.60470", + "templateHash": "17839617504395216689" }, "name": "Azure SQL Server Keys", "description": "This module deploys an Azure SQL Server Key.", diff --git a/avm/res/sql/server/main.bicep b/avm/res/sql/server/main.bicep index 3919e4655a..8115aa75d6 100644 --- a/avm/res/sql/server/main.bicep +++ b/avm/res/sql/server/main.bicep @@ -15,17 +15,20 @@ param location string = resourceGroup().location @description('Required. The name of the server.') param name string +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityAllType? @description('Conditional. The resource ID of a user assigned identity to be used by default. Required if "userAssignedIdentities" is not empty.') param primaryUserAssignedIdentityId string = '' +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. Tags of the resource.') param tags object? @@ -34,10 +37,10 @@ param tags object? param enableTelemetry bool = true @description('Optional. The databases to create in the server.') -param databases array = [] +param databases databasePropertyType[] = [] @description('Optional. The Elastic Pools to create in the server.') -param elasticPools array = [] +param elasticPools elasticPoolPropertyType[] = [] @description('Optional. The firewall rules to create in the server.') param firewallRules array = [] @@ -52,7 +55,15 @@ param securityAlertPolicies array = [] param keys array = [] @description('Conditional. The Azure Active Directory (AAD) administrator authentication. Required if no `administratorLogin` & `administratorLoginPassword` is provided.') -param administrators object = {} +param administrators serverExternalAdministratorType? + +@description('Optional. The Client id used for cross tenant CMK scenario.') +@minLength(36) +@maxLength(36) +param federatedClientId string? + +@description('Optional. A CMK URI of the key to use for encryption.') +param keyId string? @allowed([ '1.0' @@ -70,8 +81,9 @@ param minimalTlsVersion string = '1.2' @description('Optional. Whether or not to enable IPv6 support for this server.') param isIPv6Enabled string = 'Disabled' +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointSingleServiceType[]? @description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and neither firewall rules nor virtual network rules are set.') @allowed([ @@ -112,7 +124,7 @@ param encryptionProtectorObj object = {} param vulnerabilityAssessmentsObj object = {} @description('Optional. The audit settings configuration.') -param auditSettings auditSettingsType? +param auditSettings auditSettingsType = {} //Use the defaults from the child module @description('Optional. Key vault reference and secret settings for the module\'s secrets export.') param secretsExportConfiguration secretsExportConfigurationType? @@ -197,16 +209,10 @@ resource server 'Microsoft.Sql/servers@2023-08-01-preview' = { 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 ?? tenant().tenantId - } - : null + administrators: union({ administratorType: 'ActiveDirectory' }, administrators ?? {}) + federatedClientId: federatedClientId + isIPv6Enabled: isIPv6Enabled + keyId: keyId version: '12.0' minimalTlsVersion: minimalTlsVersion primaryUserAssignedIdentityId: !empty(primaryUserAssignedIdentityId) ? primaryUserAssignedIdentityId : null @@ -214,7 +220,6 @@ resource server 'Microsoft.Sql/servers@2023-08-01-preview' = { ? publicNetworkAccess : (!empty(privateEndpoints) && empty(firewallRules) && empty(virtualNetworkRules) ? 'Disabled' : null) restrictOutboundNetworkAccess: !empty(restrictOutboundNetworkAccess) ? restrictOutboundNetworkAccess : null - isIPv6Enabled: isIPv6Enabled } } @@ -249,36 +254,53 @@ module server_databases 'database/main.bicep' = [ for (database, index) in databases: { name: '${uniqueString(deployment().name, location)}-Sql-DB-${index}' params: { - name: database.name + // properties derived from parent server resource, no override allowed serverName: server.name - skuTier: database.?skuTier ?? 'GeneralPurpose' - skuName: database.?skuName ?? 'GP_Gen5_2' - skuCapacity: database.?skuCapacity - skuFamily: database.?skuFamily ?? '' - skuSize: database.?skuSize ?? '' - collation: database.?collation ?? 'SQL_Latin1_General_CP1_CI_AS' - maxSizeBytes: database.?maxSizeBytes ?? 34359738368 - autoPauseDelay: database.?autoPauseDelay ?? 0 - diagnosticSettings: database.?diagnosticSettings - isLedgerOn: database.?isLedgerOn ?? false location: location - licenseType: database.?licenseType ?? '' - maintenanceConfigurationId: database.?maintenanceConfigurationId - minCapacity: database.?minCapacity ?? '' - highAvailabilityReplicaCount: database.?highAvailabilityReplicaCount ?? 0 - readScale: database.?readScale ?? 'Disabled' - requestedBackupStorageRedundancy: database.?requestedBackupStorageRedundancy ?? '' - sampleName: database.?sampleName ?? '' + + // properties from the database object. If not provided, parent server resource properties will be used tags: database.?tags ?? tags - zoneRedundant: database.?zoneRedundant ?? true - elasticPoolId: database.?elasticPoolId ?? '' - backupShortTermRetentionPolicy: database.?backupShortTermRetentionPolicy ?? {} - backupLongTermRetentionPolicy: database.?backupLongTermRetentionPolicy ?? {} - createMode: database.?createMode ?? 'Default' - sourceDatabaseResourceId: database.?sourceDatabaseResourceId ?? '' - sourceDatabaseDeletionDate: database.?sourceDatabaseDeletionDate ?? '' - recoveryServicesRecoveryPointResourceId: database.?recoveryServicesRecoveryPointResourceId ?? '' - restorePointInTime: database.?restorePointInTime ?? '' + + // properties from the databse object. If not provided, defaults specified in the child resource will be used + name: database.name + sku: database.?sku + autoPauseDelay: database.?autoPauseDelay + availabilityZone: database.?availabilityZone + catalogCollation: database.?catalogCollation + collation: database.?collation + createMode: database.?createMode + elasticPoolResourceId: database.?elasticPoolResourceId + encryptionProtector: database.?encryptionProtector + encryptionProtectorAutoRotation: database.?encryptionProtectorAutoRotation + federatedClientId: database.?federatedClientId + freeLimitExhaustionBehavior: database.?freeLimitExhaustionBehavior + highAvailabilityReplicaCount: database.?highAvailabilityReplicaCount + isLedgerOn: database.?isLedgerOn + licenseType: database.?licenseType + longTermRetentionBackupResourceId: database.?longTermRetentionBackupResourceId + maintenanceConfigurationId: database.?maintenanceConfigurationId + manualCutover: database.?manualCutover + maxSizeBytes: database.?maxSizeBytes + minCapacity: database.?minCapacity + performCutover: database.?performCutover + preferredEnclaveType: database.?preferredEnclaveType + readScale: database.?readScale + recoverableDatabaseResourceId: database.?recoverableDatabaseResourceId + recoveryServicesRecoveryPointResourceId: database.?recoveryServicesRecoveryPointResourceId + requestedBackupStorageRedundancy: database.?requestedBackupStorageRedundancy + restorableDroppedDatabaseResourceId: database.?restorableDroppedDatabaseResourceId + restorePointInTime: database.?restorePointInTime + sampleName: database.?sampleName + secondaryType: database.?secondaryType + sourceDatabaseDeletionDate: database.?sourceDatabaseDeletionDate + sourceDatabaseResourceId: database.?sourceDatabaseResourceId + sourceResourceId: database.?sourceResourceId + useFreeLimit: database.?useFreeLimit + zoneRedundant: database.?zoneRedundant + + diagnosticSettings: database.?diagnosticSettings + backupShortTermRetentionPolicy: database.?backupShortTermRetentionPolicy + backupLongTermRetentionPolicy: database.?backupLongTermRetentionPolicy } dependsOn: [ server_elasticPools // Enables us to add databases to existing elastic pools @@ -290,21 +312,26 @@ module server_elasticPools 'elastic-pool/main.bicep' = [ for (elasticPool, index) in elasticPools: { name: '${uniqueString(deployment().name, location)}-SQLServer-ElasticPool-${index}' params: { - name: elasticPool.name + // properties derived from parent server resource, no override allowed serverName: server.name - databaseMaxCapacity: elasticPool.?databaseMaxCapacity ?? 2 - databaseMinCapacity: elasticPool.?databaseMinCapacity ?? 0 + location: location + + // properties from the elastic pool object. If not provided, parent server resource properties will be used + tags: elasticPool.?tags ?? tags + + // properties from the elastic pool object. If not provided, defaults specified in the child resource will be used + name: elasticPool.name + sku: elasticPool.?sku + autoPauseDelay: elasticPool.?autoPauseDelay + availabilityZone: elasticPool.?availabilityZone highAvailabilityReplicaCount: elasticPool.?highAvailabilityReplicaCount - licenseType: elasticPool.?licenseType ?? 'LicenseIncluded' + licenseType: elasticPool.?licenseType maintenanceConfigurationId: elasticPool.?maintenanceConfigurationId - maxSizeBytes: elasticPool.?maxSizeBytes ?? 34359738368 + maxSizeBytes: elasticPool.?maxSizeBytes minCapacity: elasticPool.?minCapacity - skuCapacity: elasticPool.?skuCapacity ?? 2 - skuName: elasticPool.?skuName ?? 'GP_Gen5' - skuTier: elasticPool.?skuTier ?? 'GeneralPurpose' - zoneRedundant: elasticPool.?zoneRedundant ?? true - location: location - tags: elasticPool.?tags ?? tags + perDatabaseSettings: elasticPool.?perDatabaseSettings + preferredEnclaveType: elasticPool.?preferredEnclaveType + zoneRedundant: elasticPool.?zoneRedundant } } ] @@ -444,23 +471,19 @@ module server_encryptionProtector 'encryption-protector/main.bicep' = if (!empty ] } -module server_audit_settings 'audit-settings/main.bicep' = if (!empty(auditSettings)) { +module server_audit_settings 'audit-settings/main.bicep' = if (auditSettings != null) { name: '${uniqueString(deployment().name, location)}-Sql-AuditSettings' params: { serverName: server.name name: auditSettings.?name ?? 'default' - state: auditSettings.?state ?? 'Disabled' - auditActionsAndGroups: auditSettings.?auditActionsAndGroups ?? [ - 'BATCH_COMPLETED_GROUP' - 'SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP' - 'FAILED_DATABASE_AUTHENTICATION_GROUP' - ] - isAzureMonitorTargetEnabled: auditSettings.?isAzureMonitorTargetEnabled ?? false - isDevopsAuditEnabled: auditSettings.?isDevopsAuditEnabled ?? false - isManagedIdentityInUse: auditSettings.?isManagedIdentityInUse ?? false - isStorageSecondaryKeyInUse: auditSettings.?isStorageSecondaryKeyInUse ?? false - queueDelayMs: auditSettings.?queueDelayMs ?? 1000 - retentionDays: auditSettings.?retentionDays ?? 90 + state: auditSettings.?state + auditActionsAndGroups: auditSettings.?auditActionsAndGroups + isAzureMonitorTargetEnabled: auditSettings.?isAzureMonitorTargetEnabled + isDevopsAuditEnabled: auditSettings.?isDevopsAuditEnabled + isManagedIdentityInUse: auditSettings.?isManagedIdentityInUse + isStorageSecondaryKeyInUse: auditSettings.?isStorageSecondaryKeyInUse + queueDelayMs: auditSettings.?queueDelayMs + retentionDays: auditSettings.?retentionDays storageAccountResourceId: auditSettings.?storageAccountResourceId } } @@ -510,6 +533,7 @@ output systemAssignedMIPrincipalId string = server.?identity.?principalId ?? '' @description('The location the resource was deployed into.') output location string = server.location +import { secretsOutputType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.') output exportedSecrets secretsOutputType = (secretsExportConfiguration != null) ? toObject(secretsExport.outputs.secretsSet, secret => last(split(secret.secretResourceId, '/')), secret => secret) @@ -530,180 +554,248 @@ output privateEndpoints array = [ // Definitions // // =============== // -type managedIdentitiesType = { - @description('Optional. Enables system assigned managed identity on the resource.') - systemAssigned: bool? +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' +import { elasticPoolPerDatabaseSettingsType, elasticPoolSkuType } from 'elastic-pool/main.bicep' +import { databaseSkuType, shortTermBackupRetentionPolicyType, longTermBackupRetentionPolicyType } from 'database/main.bicep' - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[]? -}? - -type lockType = { - @description('Optional. Specify the name of lock.') +@export() +type auditSettingsType = { + @description('Optional. Specifies the name of the audit settings.') name: string? - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? + @description('Optional. Specifies the Actions-Groups and Actions to audit.') + auditActionsAndGroups: string[]? -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? + @description('Optional. Specifies whether audit events are sent to Azure Monitor.') + isAzureMonitorTargetEnabled: bool? - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string + @description('Optional. Specifies the state of devops audit. If state is Enabled, devops logs will be sent to Azure Monitor.') + isDevopsAuditEnabled: bool? - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string + @description('Optional. Specifies whether Managed Identity is used to access blob storage.') + isManagedIdentityInUse: bool? - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + @description('Optional. Specifies whether storageAccountAccessKey value is the storage\'s secondary key.') + isStorageSecondaryKeyInUse: bool? - @description('Optional. The description of the role assignment.') - description: string? + @description('Optional. Specifies the amount of time in milliseconds that can elapse before audit actions are forced to be processed.') + queueDelayMs: int? - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? + @description('Optional. Specifies the number of days to keep in the audit logs in the storage account.') + retentionDays: int? - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? + @description('Optional. Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required.') + state: 'Enabled' | 'Disabled'? - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? + @description('Optional. Specifies the identifier key of the auditing storage account.') + storageAccountResourceId: string? +} -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? +@export() +type secretsExportConfigurationType = { + @description('Required. The resource ID of the key vault where to store the secrets of this module.') + keyVaultResourceId: string - @description('Optional. The location to deploy the private endpoint to.') - location: string? + @description('Optional. The sqlAdminPassword secret name to create.') + sqlAdminPasswordSecretName: string? - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? + @description('Optional. The sqlAzureConnectionString secret name to create.') + sqlAzureConnectionStringSercretName: string? +} - @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') - service: string? +@export() +type serverExternalAdministratorType = { + @description('Optional. Type of the sever administrator.') + administratorType: 'ActiveDirectory'? - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string + @description('Required. Azure Active Directory only Authentication enabled.') + azureADOnlyAuthentication: bool - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? + @description('Required. Login name of the server administrator.') + login: string - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? + @description('Required. Principal Type of the sever administrator.') + principalType: 'Application' | 'Group' | 'User' - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? + @description('Required. SID (object ID) of the server administrator.') + sid: string - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? + @description('Optional. Tenant ID of the administrator.') + tenantId: string? +} - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? +@export() +type databasePropertyType = { + @description('Required. The name of the Elastic Pool.') + name: string - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? + @description('Optional. Tags of the resource.') + tags: object? - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? + @description('Optional. The database SKU.') + sku: databaseSkuType? - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string + @description('Optional. Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled.') + autoPauseDelay: int? - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string + @description('Optional. Specifies the availability zone the database is pinned to.') + availabilityZone: '1' | '2' | '3' | 'NoPreference'? - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string + @description('Optional. Collation of the metadata catalog.') + catalogCollation: string? - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? + @description('Optional. The collation of the database.') + collation: string? - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? + @description('Optional. Specifies the mode of database creation.') + createMode: + | 'Copy' + | 'Default' + | 'OnlineSecondary' + | 'PointInTimeRestore' + | 'Recovery' + | 'Restore' + | 'RestoreExternalBackup' + | 'RestoreExternalBackupSecondary' + | 'RestoreLongTermRetentionBackup' + | 'Secondary'? - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? + @description('Optional. The resource identifier of the elastic pool containing this database.') + elasticPoolResourceId: string? - @description('Optional. Specify the type of lock.') - lock: lockType + @description('Optional. The azure key vault URI of the database if it\'s configured with per Database Customer Managed Keys.') + encryptionProtector: string? - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType + @description('Optional. The flag to enable or disable auto rotation of database encryption protector AKV key.') + encryptionProtectorAutoRotation: bool? - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? + @description('Optional. The Client id used for cross tenant per database CMK scenario.') + @minLength(36) + @maxLength(36) + federatedClientId: string? - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? + @description('Optional. Specifies the behavior when monthly free limits are exhausted for the free database.') + freeLimitExhaustionBehavior: 'AutoPause' | 'BillOverUsage'? - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? + @description('Optional. The number of secondary replicas associated with the database that are used to provide high availability. Not applicable to a Hyperscale database within an elastic pool.') + highAvailabilityReplicaCount: int? -type auditSettingsType = { - @description('Optional. Specifies the name of the audit settings.') - name: string? + @description('Optional. Whether or not this database is a ledger database, which means all tables in the database are ledger tables.') + isLedgerOn: bool? - @description('Optional. Specifies the Actions-Groups and Actions to audit.') - auditActionsAndGroups: string[]? + // keys + @description('Optional. The license type to apply for this database.') + licenseType: 'BasePrice' | 'LicenseIncluded'? - @description('Optional. Specifies whether audit events are sent to Azure Monitor.') - isAzureMonitorTargetEnabled: bool? + @description('Optional. The resource identifier of the long term retention backup associated with create operation of this database.') + longTermRetentionBackupResourceId: string? - @description('Optional. Specifies the state of devops audit. If state is Enabled, devops logs will be sent to Azure Monitor.') - isDevopsAuditEnabled: bool? + @description('Optional. Maintenance configuration id assigned to the database. This configuration defines the period when the maintenance updates will occur.') + maintenanceConfigurationId: string? - @description('Optional. Specifies whether Managed Identity is used to access blob storage.') - isManagedIdentityInUse: bool? + @description('Optional. Whether or not customer controlled manual cutover needs to be done during Update Database operation to Hyperscale tier.') + manualCutover: bool? - @description('Optional. Specifies whether storageAccountAccessKey value is the storage\'s secondary key.') - isStorageSecondaryKeyInUse: bool? + @description('Optional. The max size of the database expressed in bytes.') + maxSizeBytes: int? - @description('Optional. Specifies the amount of time in milliseconds that can elapse before audit actions are forced to be processed.') - queueDelayMs: int? + // string to enable fractional values + @description('Optional. Minimal capacity that database will always have allocated, if not paused.') + minCapacity: string? - @description('Optional. Specifies the number of days to keep in the audit logs in the storage account.') - retentionDays: int? + @description('Optional. To trigger customer controlled manual cutover during the wait state while Scaling operation is in progress.') + performCutover: bool? - @description('Required. Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required.') - state: 'Enabled' | 'Disabled' + @description('Optional. Type of enclave requested on the database.') + preferredEnclaveType: 'Default' | 'VBS'? - @description('Optional. Specifies the identifier key of the auditing storage account.') - storageAccountResourceId: string? + @description('Optional. The state of read-only routing. If enabled, connections that have application intent set to readonly in their connection string may be routed to a readonly secondary replica in the same region. Not applicable to a Hyperscale database within an elastic pool.') + readScale: 'Disabled' | 'Enabled'? + + @description('Optional. The resource identifier of the recoverable database associated with create operation of this database.') + recoverableDatabaseResourceId: string? + + @description('Optional. The resource identifier of the recovery point associated with create operation of this database.') + recoveryServicesRecoveryPointResourceId: string? + + @description('Optional. The storage account type to be used to store backups for this database.') + requestedBackupStorageRedundancy: 'Geo' | 'GeoZone' | 'Local' | 'Zone'? + + @description('Optional. The resource identifier of the restorable dropped database associated with create operation of this database.') + restorableDroppedDatabaseResourceId: string? + + @description('Optional. Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database.') + restorePointInTime: string? + + @description('Optional. The name of the sample schema to apply when creating this database.') + sampleName: string? + + @description('Optional. The secondary type of the database if it is a secondary.') + secondaryType: 'Geo' | 'Named' | 'Standby'? + + @description('Optional. Specifies the time that the database was deleted.') + sourceDatabaseDeletionDate: string? + + @description('Optional. The resource identifier of the source database associated with create operation of this database.') + sourceDatabaseResourceId: string? + + @description('Optional. The resource identifier of the source associated with the create operation of this database.') + sourceResourceId: string? + + @description('Optional. Whether or not the database uses free monthly limits. Allowed on one database in a subscription.') + useFreeLimit: bool? + + @description('Optional. Whether or not this database is zone redundant, which means the replicas of this database will be spread across multiple availability zones.') + zoneRedundant: bool? + + @description('Optional. The diagnostic settings of the service.') + diagnosticSettings: diagnosticSettingFullType[]? + + @description('Optional. The short term backup retention policy for the database.') + backupShortTermRetentionPolicy: shortTermBackupRetentionPolicyType? + + @description('Optional. The long term backup retention policy for the database.') + backupLongTermRetentionPolicy: longTermBackupRetentionPolicyType? } -type secretsExportConfigurationType = { - @description('Required. The resource ID of the key vault where to store the secrets of this module.') - keyVaultResourceId: string +@export() +type elasticPoolPropertyType = { + @description('Required. The name of the Elastic Pool.') + name: string - @description('Optional. The sqlAdminPassword secret name to create.') - sqlAdminPasswordSecretName: string? + @description('Optional. Tags of the resource.') + tags: object? - @description('Optional. The sqlAzureConnectionString secret name to create.') - sqlAzureConnectionStringSercretName: string? -}? + @description('Optional. The elastic pool SKU.') + sku: elasticPoolSkuType? + + @description('Optional. Time in minutes after which elastic pool is automatically paused. A value of -1 means that automatic pause is disabled.') + autoPauseDelay: int? + + @description('Optional. Specifies the availability zone the pool\'s primary replica is pinned to.') + availabilityZone: '1' | '2' | '3' | 'NoPreference'? + + @description('Optional. The number of secondary replicas associated with the elastic pool that are used to provide high availability. Applicable only to Hyperscale elastic pools.') + highAvailabilityReplicaCount: int? + + @description('Optional. The license type to apply for this elastic pool.') + licenseType: 'BasePrice' | 'LicenseIncluded'? + + @description('Optional. Maintenance configuration id assigned to the elastic pool. This configuration defines the period when the maintenance updates will will occur.') + maintenanceConfigurationId: string? + + @description('Optional. The storage limit for the database elastic pool in bytes.') + maxSizeBytes: int? + + @description('Optional. Minimal capacity that serverless pool will not shrink below, if not paused.') + minCapacity: int? + + @description('Optional. The per database settings for the elastic pool.') + perDatabaseSettings: elasticPoolPerDatabaseSettingsType? + + @description('Optional. Type of enclave requested on the elastic pool.') + preferredEnclaveType: 'Default' | 'VBS'? -import { secretSetType } from 'modules/keyVaultExport.bicep' -type secretsOutputType = { - @description('An exported secret\'s references.') - *: secretSetType + @description('Optional. Whether or not this elastic pool is zone redundant, which means the replicas of this elastic pool will be spread across multiple availability zones.') + zoneRedundant: bool? } diff --git a/avm/res/sql/server/main.json b/avm/res/sql/server/main.json index 66bd386f4d..0434d51bda 100644 --- a/avm/res/sql/server/main.json +++ b/avm/res/sql/server/main.json @@ -5,355 +5,14 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12721468399061919493" + "version": "0.30.23.60470", + "templateHash": "14327182870559615261" }, "name": "Azure SQL Servers", "description": "This module deploys an Azure SQL Server.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { - "type": "object", - "properties": { - "systemAssigned": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." - } - }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." - } - } - }, - "nullable": true - }, - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." - } - }, - "privateDnsZoneGroup": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." - } - }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, - "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } - }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } - } - } - }, - "nullable": true - }, "auditSettingsType": { "type": "object", "properties": { @@ -422,8 +81,9 @@ "Disabled", "Enabled" ], + "nullable": true, "metadata": { - "description": "Required. Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required." + "description": "Optional. Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required." } }, "storageAccountResourceId": { @@ -433,6 +93,9 @@ "description": "Optional. Specifies the identifier key of the auditing storage account." } } + }, + "metadata": { + "__bicep_export!": true } }, "secretsExportConfigurationType": { @@ -459,71 +122,1305 @@ } } }, - "nullable": true - }, - "secretsOutputType": { - "type": "object", - "properties": {}, - "additionalProperties": { - "$ref": "#/definitions/secretSetType", - "metadata": { - "description": "An exported secret's references." - } + "metadata": { + "__bicep_export!": true } }, - "secretSetType": { + "serverExternalAdministratorType": { "type": "object", "properties": { - "secretResourceId": { + "administratorType": { "type": "string", + "allowedValues": [ + "ActiveDirectory" + ], + "nullable": true, "metadata": { - "description": "The resourceId of the exported secret." + "description": "Optional. Type of the sever administrator." } }, - "secretUri": { + "azureADOnlyAuthentication": { + "type": "bool", + "metadata": { + "description": "Required. Azure Active Directory only Authentication enabled." + } + }, + "login": { "type": "string", "metadata": { - "description": "The secret URI of the exported secret." + "description": "Required. Login name of the server administrator." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Application", + "Group", + "User" + ], + "metadata": { + "description": "Required. Principal Type of the sever administrator." + } + }, + "sid": { + "type": "string", + "metadata": { + "description": "Required. SID (object ID) of the server administrator." + } + }, + "tenantId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Tenant ID of the administrator." } } }, "metadata": { - "__bicep_imported_from!": { - "sourceTemplate": "modules/keyVaultExport.bicep" - } - } - } - }, - "parameters": { - "administratorLogin": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Conditional. The administrator username for the server. Required if no `administrators` object for AAD authentication is provided." - } - }, - "administratorLoginPassword": { - "type": "securestring", - "defaultValue": "", - "metadata": { - "description": "Conditional. The administrator login password. Required if no `administrators` object for AAD authentication is provided." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." + "__bicep_export!": true } }, - "name": { - "type": "string", + "databasePropertyType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Elastic Pool." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "sku": { + "$ref": "#/definitions/databaseSkuType", + "nullable": true, + "metadata": { + "description": "Optional. The database SKU." + } + }, + "autoPauseDelay": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled." + } + }, + "availabilityZone": { + "type": "string", + "allowedValues": [ + "1", + "2", + "3", + "NoPreference" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the availability zone the database is pinned to." + } + }, + "catalogCollation": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Collation of the metadata catalog." + } + }, + "collation": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The collation of the database." + } + }, + "createMode": { + "type": "string", + "allowedValues": [ + "Copy", + "Default", + "OnlineSecondary", + "PointInTimeRestore", + "Recovery", + "Restore", + "RestoreExternalBackup", + "RestoreExternalBackupSecondary", + "RestoreLongTermRetentionBackup", + "Secondary" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the mode of database creation." + } + }, + "elasticPoolResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource identifier of the elastic pool containing this database." + } + }, + "encryptionProtector": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The azure key vault URI of the database if it's configured with per Database Customer Managed Keys." + } + }, + "encryptionProtectorAutoRotation": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The flag to enable or disable auto rotation of database encryption protector AKV key." + } + }, + "federatedClientId": { + "type": "string", + "nullable": true, + "minLength": 36, + "maxLength": 36, + "metadata": { + "description": "Optional. The Client id used for cross tenant per database CMK scenario." + } + }, + "freeLimitExhaustionBehavior": { + "type": "string", + "allowedValues": [ + "AutoPause", + "BillOverUsage" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the behavior when monthly free limits are exhausted for the free database." + } + }, + "highAvailabilityReplicaCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The number of secondary replicas associated with the database that are used to provide high availability. Not applicable to a Hyperscale database within an elastic pool." + } + }, + "isLedgerOn": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether or not this database is a ledger database, which means all tables in the database are ledger tables." + } + }, + "licenseType": { + "type": "string", + "allowedValues": [ + "BasePrice", + "LicenseIncluded" + ], + "nullable": true, + "metadata": { + "description": "Optional. The license type to apply for this database." + } + }, + "longTermRetentionBackupResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource identifier of the long term retention backup associated with create operation of this database." + } + }, + "maintenanceConfigurationId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Maintenance configuration id assigned to the database. This configuration defines the period when the maintenance updates will occur." + } + }, + "manualCutover": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether or not customer controlled manual cutover needs to be done during Update Database operation to Hyperscale tier." + } + }, + "maxSizeBytes": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The max size of the database expressed in bytes." + } + }, + "minCapacity": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Minimal capacity that database will always have allocated, if not paused." + } + }, + "performCutover": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. To trigger customer controlled manual cutover during the wait state while Scaling operation is in progress." + } + }, + "preferredEnclaveType": { + "type": "string", + "allowedValues": [ + "Default", + "VBS" + ], + "nullable": true, + "metadata": { + "description": "Optional. Type of enclave requested on the database." + } + }, + "readScale": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. The state of read-only routing. If enabled, connections that have application intent set to readonly in their connection string may be routed to a readonly secondary replica in the same region. Not applicable to a Hyperscale database within an elastic pool." + } + }, + "recoverableDatabaseResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource identifier of the recoverable database associated with create operation of this database." + } + }, + "recoveryServicesRecoveryPointResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource identifier of the recovery point associated with create operation of this database." + } + }, + "requestedBackupStorageRedundancy": { + "type": "string", + "allowedValues": [ + "Geo", + "GeoZone", + "Local", + "Zone" + ], + "nullable": true, + "metadata": { + "description": "Optional. The storage account type to be used to store backups for this database." + } + }, + "restorableDroppedDatabaseResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource identifier of the restorable dropped database associated with create operation of this database." + } + }, + "restorePointInTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database." + } + }, + "sampleName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the sample schema to apply when creating this database." + } + }, + "secondaryType": { + "type": "string", + "allowedValues": [ + "Geo", + "Named", + "Standby" + ], + "nullable": true, + "metadata": { + "description": "Optional. The secondary type of the database if it is a secondary." + } + }, + "sourceDatabaseDeletionDate": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specifies the time that the database was deleted." + } + }, + "sourceDatabaseResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource identifier of the source database associated with create operation of this database." + } + }, + "sourceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource identifier of the source associated with the create operation of this database." + } + }, + "useFreeLimit": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether or not the database uses free monthly limits. Allowed on one database in a subscription." + } + }, + "zoneRedundant": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether or not this database is zone redundant, which means the replicas of this database will be spread across multiple availability zones." + } + }, + "diagnosticSettings": { + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "backupShortTermRetentionPolicy": { + "$ref": "#/definitions/shortTermBackupRetentionPolicyType", + "nullable": true, + "metadata": { + "description": "Optional. The short term backup retention policy for the database." + } + }, + "backupLongTermRetentionPolicy": { + "$ref": "#/definitions/longTermBackupRetentionPolicyType", + "nullable": true, + "metadata": { + "description": "Optional. The long term backup retention policy for the database." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "elasticPoolPropertyType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Elastic Pool." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "sku": { + "$ref": "#/definitions/elasticPoolSkuType", + "nullable": true, + "metadata": { + "description": "Optional. The elastic pool SKU." + } + }, + "autoPauseDelay": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Time in minutes after which elastic pool is automatically paused. A value of -1 means that automatic pause is disabled." + } + }, + "availabilityZone": { + "type": "string", + "allowedValues": [ + "1", + "2", + "3", + "NoPreference" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the availability zone the pool's primary replica is pinned to." + } + }, + "highAvailabilityReplicaCount": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The number of secondary replicas associated with the elastic pool that are used to provide high availability. Applicable only to Hyperscale elastic pools." + } + }, + "licenseType": { + "type": "string", + "allowedValues": [ + "BasePrice", + "LicenseIncluded" + ], + "nullable": true, + "metadata": { + "description": "Optional. The license type to apply for this elastic pool." + } + }, + "maintenanceConfigurationId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Maintenance configuration id assigned to the elastic pool. This configuration defines the period when the maintenance updates will will occur." + } + }, + "maxSizeBytes": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The storage limit for the database elastic pool in bytes." + } + }, + "minCapacity": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Minimal capacity that serverless pool will not shrink below, if not paused." + } + }, + "perDatabaseSettings": { + "$ref": "#/definitions/elasticPoolPerDatabaseSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. The per database settings for the elastic pool." + } + }, + "preferredEnclaveType": { + "type": "string", + "allowedValues": [ + "Default", + "VBS" + ], + "nullable": true, + "metadata": { + "description": "Optional. Type of enclave requested on the elastic pool." + } + }, + "zoneRedundant": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether or not this elastic pool is zone redundant, which means the replicas of this elastic pool will be spread across multiple availability zones." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "_1.privateEndpointCustomDnsConfigType": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS Zone Group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.secretSetOutputType": { + "type": "object", + "properties": { + "secretResourceId": { + "type": "string", + "metadata": { + "description": "The resourceId of the exported secret." + } + }, + "secretUri": { + "type": "string", + "metadata": { + "description": "The secret URI of the exported secret." + } + }, + "secretUriWithVersion": { + "type": "string", + "metadata": { + "description": "The secret URI with version of the exported secret." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for the output of the secret set via the secrets export feature.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "databaseSkuType": { + "type": "object", + "properties": { + "capacity": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The capacity of the particular SKU." + } + }, + "family": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SKU, typically, a letter + Number code, e.g. P3." + } + }, + "size": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Size of the particular SKU." + } + }, + "tier": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tier or edition of the particular SKU, e.g. Basic, Premium." + } + } + }, + "metadata": { + "description": "The database SKU.", + "__bicep_imported_from!": { + "sourceTemplate": "database/main.bicep" + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "elasticPoolPerDatabaseSettingsType": { + "type": "object", + "properties": { + "autoPauseDelay": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Auto Pause Delay for per database within pool." + } + }, + "maxCapacity": { + "type": "string", + "metadata": { + "description": "Required. The maximum capacity any one database can consume. Examples: '0.5', '2'." + } + }, + "minCapacity": { + "type": "string", + "metadata": { + "description": "Required. The minimum capacity all databases are guaranteed. Examples: '0.5', '1'." + } + } + }, + "metadata": { + "description": "The per database settings for the elastic pool.", + "__bicep_imported_from!": { + "sourceTemplate": "elastic-pool/main.bicep" + } + } + }, + "elasticPoolSkuType": { + "type": "object", + "properties": { + "capacity": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The capacity of the particular SKU." + } + }, + "family": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here." + } + }, + "name": { + "type": "string", + "allowedValues": [ + "BC_DC", + "BC_Gen5", + "BasicPool", + "GP_DC", + "GP_FSv2", + "GP_Gen5", + "HS_Gen5", + "HS_MOPRMS", + "HS_PRMS", + "PremiumPool", + "ServerlessPool", + "StandardPool" + ], + "metadata": { + "description": "Required. The name of the SKU, typically, a letter + Number code, e.g. P3." + } + }, + "size": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Size of the particular SKU." + } + }, + "tier": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tier or edition of the particular SKU, e.g. Basic, Premium." + } + } + }, + "metadata": { + "description": "The elastic pool SKU.", + "__bicep_imported_from!": { + "sourceTemplate": "elastic-pool/main.bicep" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "longTermBackupRetentionPolicyType": { + "type": "object", + "properties": { + "backupStorageAccessTier": { + "type": "string", + "allowedValues": [ + "Archive", + "Hot" + ], + "nullable": true, + "metadata": { + "description": "Optional. The BackupStorageAccessTier for the LTR backups." + } + }, + "makeBackupsImmutable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The setting whether to make LTR backups immutable." + } + }, + "monthlyRetention": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Monthly retention in ISO 8601 duration format." + } + }, + "weeklyRetention": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Weekly retention in ISO 8601 duration format." + } + }, + "weekOfYear": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Week of year backup to keep for yearly retention." + } + }, + "yearlyRetention": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Yearly retention in ISO 8601 duration format." + } + } + }, + "metadata": { + "description": "The long-term backup retention policy for the database.", + "__bicep_imported_from!": { + "sourceTemplate": "database/main.bicep" + } + } + }, + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "privateEndpointSingleServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private Endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the Private Endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the Private Endpoint for. For example \"vault\" for a Key Vault Private Endpoint." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS Zone Group to configure for the Private Endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the Private Endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the Private Endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/Resource Groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like 'vault' for key vault).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "secretsOutputType": { + "type": "object", + "properties": {}, + "additionalProperties": { + "$ref": "#/definitions/_1.secretSetOutputType", + "metadata": { + "description": "An exported secret's references." + } + }, + "metadata": { + "description": "A map of the exported secrets", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "shortTermBackupRetentionPolicyType": { + "type": "object", + "properties": { + "diffBackupIntervalInHours": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Differential backup interval in hours. For Hyperscale tiers this value will be ignored." + } + }, + "retentionDays": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Point-in-time retention in days." + } + } + }, + "metadata": { + "description": "The short-term backup retention policy for the database.", + "__bicep_imported_from!": { + "sourceTemplate": "database/main.bicep" + } + } + } + }, + "parameters": { + "administratorLogin": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. The administrator username for the server. Required if no `administrators` object for AAD authentication is provided." + } + }, + "administratorLoginPassword": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Conditional. The administrator login password. Required if no `administrators` object for AAD authentication is provided." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "name": { + "type": "string", "metadata": { "description": "Required. The name of the server." } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } @@ -537,12 +1434,17 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -563,6 +1465,9 @@ }, "databases": { "type": "array", + "items": { + "$ref": "#/definitions/databasePropertyType" + }, "defaultValue": [], "metadata": { "description": "Optional. The databases to create in the server." @@ -570,6 +1475,9 @@ }, "elasticPools": { "type": "array", + "items": { + "$ref": "#/definitions/elasticPoolPropertyType" + }, "defaultValue": [], "metadata": { "description": "Optional. The Elastic Pools to create in the server." @@ -604,12 +1512,28 @@ } }, "administrators": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/serverExternalAdministratorType", + "nullable": true, "metadata": { "description": "Conditional. The Azure Active Directory (AAD) administrator authentication. Required if no `administratorLogin` & `administratorLoginPassword` is provided." } }, + "federatedClientId": { + "type": "string", + "nullable": true, + "minLength": 36, + "maxLength": 36, + "metadata": { + "description": "Optional. The Client id used for cross tenant CMK scenario." + } + }, + "keyId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A CMK URI of the key to use for encryption." + } + }, "minimalTlsVersion": { "type": "string", "defaultValue": "1.2", @@ -635,7 +1559,11 @@ } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointSingleServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } @@ -681,7 +1609,7 @@ }, "auditSettings": { "$ref": "#/definitions/auditSettingsType", - "nullable": true, + "defaultValue": {}, "metadata": { "description": "Optional. The audit settings configuration." } @@ -750,13 +1678,15 @@ "properties": { "administratorLogin": "[if(not(empty(parameters('administratorLogin'))), parameters('administratorLogin'), null())]", "administratorLoginPassword": "[if(not(empty(parameters('administratorLoginPassword'))), parameters('administratorLoginPassword'), null())]", - "administrators": "[if(not(empty(parameters('administrators'))), createObject('administratorType', 'ActiveDirectory', 'azureADOnlyAuthentication', parameters('administrators').azureADOnlyAuthentication, 'login', parameters('administrators').login, 'principalType', parameters('administrators').principalType, 'sid', parameters('administrators').sid, 'tenantId', coalesce(tryGet(parameters('administrators'), 'tenantId'), tenant().tenantId)), null())]", + "administrators": "[union(createObject('administratorType', 'ActiveDirectory'), coalesce(parameters('administrators'), createObject()))]", + "federatedClientId": "[parameters('federatedClientId')]", + "isIPv6Enabled": "[parameters('isIPv6Enabled')]", + "keyId": "[parameters('keyId')]", "version": "12.0", "minimalTlsVersion": "[parameters('minimalTlsVersion')]", "primaryUserAssignedIdentityId": "[if(not(empty(parameters('primaryUserAssignedIdentityId'))), parameters('primaryUserAssignedIdentityId'), null())]", "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), parameters('publicNetworkAccess'), if(and(and(not(empty(parameters('privateEndpoints'))), empty(parameters('firewallRules'))), empty(parameters('virtualNetworkRules'))), 'Disabled', null()))]", - "restrictOutboundNetworkAccess": "[if(not(empty(parameters('restrictOutboundNetworkAccess'))), parameters('restrictOutboundNetworkAccess'), null())]", - "isIPv6Enabled": "[parameters('isIPv6Enabled')]" + "restrictOutboundNetworkAccess": "[if(not(empty(parameters('restrictOutboundNetworkAccess'))), parameters('restrictOutboundNetworkAccess'), null())]" } }, "server_lock": { @@ -809,95 +1739,128 @@ }, "mode": "Incremental", "parameters": { - "name": { - "value": "[parameters('databases')[copyIndex()].name]" - }, "serverName": { "value": "[parameters('name')]" }, - "skuTier": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'skuTier'), 'GeneralPurpose')]" + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'tags'), parameters('tags'))]" + }, + "name": { + "value": "[parameters('databases')[copyIndex()].name]" }, - "skuName": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'skuName'), 'GP_Gen5_2')]" + "sku": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'sku')]" }, - "skuCapacity": { - "value": "[tryGet(parameters('databases')[copyIndex()], 'skuCapacity')]" + "autoPauseDelay": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'autoPauseDelay')]" }, - "skuFamily": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'skuFamily'), '')]" + "availabilityZone": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'availabilityZone')]" }, - "skuSize": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'skuSize'), '')]" + "catalogCollation": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'catalogCollation')]" }, "collation": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'collation'), 'SQL_Latin1_General_CP1_CI_AS')]" + "value": "[tryGet(parameters('databases')[copyIndex()], 'collation')]" }, - "maxSizeBytes": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'maxSizeBytes'), json('34359738368'))]" + "createMode": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'createMode')]" }, - "autoPauseDelay": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'autoPauseDelay'), 0)]" + "elasticPoolResourceId": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'elasticPoolResourceId')]" }, - "diagnosticSettings": { - "value": "[tryGet(parameters('databases')[copyIndex()], 'diagnosticSettings')]" + "encryptionProtector": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'encryptionProtector')]" }, - "isLedgerOn": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'isLedgerOn'), false())]" + "encryptionProtectorAutoRotation": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'encryptionProtectorAutoRotation')]" }, - "location": { - "value": "[parameters('location')]" + "federatedClientId": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'federatedClientId')]" + }, + "freeLimitExhaustionBehavior": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'freeLimitExhaustionBehavior')]" + }, + "highAvailabilityReplicaCount": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'highAvailabilityReplicaCount')]" + }, + "isLedgerOn": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'isLedgerOn')]" }, "licenseType": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'licenseType'), '')]" + "value": "[tryGet(parameters('databases')[copyIndex()], 'licenseType')]" + }, + "longTermRetentionBackupResourceId": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'longTermRetentionBackupResourceId')]" }, "maintenanceConfigurationId": { "value": "[tryGet(parameters('databases')[copyIndex()], 'maintenanceConfigurationId')]" }, + "manualCutover": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'manualCutover')]" + }, + "maxSizeBytes": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'maxSizeBytes')]" + }, "minCapacity": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'minCapacity'), '')]" + "value": "[tryGet(parameters('databases')[copyIndex()], 'minCapacity')]" }, - "highAvailabilityReplicaCount": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'highAvailabilityReplicaCount'), 0)]" + "performCutover": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'performCutover')]" + }, + "preferredEnclaveType": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'preferredEnclaveType')]" }, "readScale": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'readScale'), 'Disabled')]" + "value": "[tryGet(parameters('databases')[copyIndex()], 'readScale')]" }, - "requestedBackupStorageRedundancy": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'requestedBackupStorageRedundancy'), '')]" + "recoverableDatabaseResourceId": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'recoverableDatabaseResourceId')]" }, - "sampleName": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'sampleName'), '')]" + "recoveryServicesRecoveryPointResourceId": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'recoveryServicesRecoveryPointResourceId')]" }, - "tags": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'tags'), parameters('tags'))]" + "requestedBackupStorageRedundancy": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'requestedBackupStorageRedundancy')]" }, - "zoneRedundant": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'zoneRedundant'), true())]" + "restorableDroppedDatabaseResourceId": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'restorableDroppedDatabaseResourceId')]" }, - "elasticPoolId": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'elasticPoolId'), '')]" + "restorePointInTime": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'restorePointInTime')]" }, - "backupShortTermRetentionPolicy": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'backupShortTermRetentionPolicy'), createObject())]" + "sampleName": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'sampleName')]" }, - "backupLongTermRetentionPolicy": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'backupLongTermRetentionPolicy'), createObject())]" + "secondaryType": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'secondaryType')]" }, - "createMode": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'createMode'), 'Default')]" + "sourceDatabaseDeletionDate": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'sourceDatabaseDeletionDate')]" }, "sourceDatabaseResourceId": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'sourceDatabaseResourceId'), '')]" + "value": "[tryGet(parameters('databases')[copyIndex()], 'sourceDatabaseResourceId')]" }, - "sourceDatabaseDeletionDate": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'sourceDatabaseDeletionDate'), '')]" + "sourceResourceId": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'sourceResourceId')]" }, - "recoveryServicesRecoveryPointResourceId": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'recoveryServicesRecoveryPointResourceId'), '')]" + "useFreeLimit": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'useFreeLimit')]" }, - "restorePointInTime": { - "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'restorePointInTime'), '')]" + "zoneRedundant": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'zoneRedundant')]" + }, + "diagnosticSettings": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'diagnosticSettings')]" + }, + "backupShortTermRetentionPolicy": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'backupShortTermRetentionPolicy')]" + }, + "backupLongTermRetentionPolicy": { + "value": "[tryGet(parameters('databases')[copyIndex()], 'backupLongTermRetentionPolicy')]" } }, "template": { @@ -907,133 +1870,256 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "18021918128213514276" + "version": "0.30.23.60470", + "templateHash": "18018827030977470456" }, "name": "SQL Server Database", "description": "This module deploys an Azure SQL Server Database.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "databaseSkuType": { + "type": "object", + "properties": { + "capacity": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The capacity of the particular SKU." + } + }, + "family": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SKU, typically, a letter + Number code, e.g. P3." + } + }, + "size": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Size of the particular SKU." + } + }, + "tier": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tier or edition of the particular SKU, e.g. Basic, Premium." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The database SKU." + } + }, + "shortTermBackupRetentionPolicyType": { + "type": "object", + "properties": { + "diffBackupIntervalInHours": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Differential backup interval in hours. For Hyperscale tiers this value will be ignored." + } + }, + "retentionDays": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Point-in-time retention in days." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The short-term backup retention policy for the database." + } + }, + "longTermBackupRetentionPolicyType": { + "type": "object", + "properties": { + "backupStorageAccessTier": { + "type": "string", + "allowedValues": [ + "Archive", + "Hot" + ], + "nullable": true, + "metadata": { + "description": "Optional. The BackupStorageAccessTier for the LTR backups." + } + }, + "makeBackupsImmutable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The setting whether to make LTR backups immutable." + } + }, + "monthlyRetention": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Monthly retention in ISO 8601 duration format." + } + }, + "weeklyRetention": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Weekly retention in ISO 8601 duration format." + } + }, + "weekOfYear": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Week of year backup to keep for yearly retention." + } + }, + "yearlyRetention": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Yearly retention in ISO 8601 duration format." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The long-term backup retention policy for the database." + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." } }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -1049,6 +2135,43 @@ "description": "Conditional. The name of the parent SQL Server. Required if the template is used in a standalone deployment." } }, + "sku": { + "$ref": "#/definitions/databaseSkuType", + "defaultValue": { + "name": "GP_Gen5_2", + "tier": "GeneralPurpose" + }, + "metadata": { + "description": "Optional. The database SKU." + } + }, + "autoPauseDelay": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled." + } + }, + "availabilityZone": { + "type": "string", + "allowedValues": [ + "1", + "2", + "3", + "NoPreference" + ], + "defaultValue": "NoPreference", + "metadata": { + "description": "Optional. Specifies the availability zone the database is pinned to." + } + }, + "catalogCollation": { + "type": "string", + "defaultValue": "DATABASE_DEFAULT", + "metadata": { + "description": "Optional. Collation of the metadata catalog." + } + }, "collation": { "type": "string", "defaultValue": "SQL_Latin1_General_CP1_CI_AS", @@ -1056,51 +2179,110 @@ "description": "Optional. The collation of the database." } }, - "skuTier": { + "createMode": { + "type": "string", + "allowedValues": [ + "Copy", + "Default", + "OnlineSecondary", + "PointInTimeRestore", + "Recovery", + "Restore", + "RestoreExternalBackup", + "RestoreExternalBackupSecondary", + "RestoreLongTermRetentionBackup", + "Secondary" + ], + "defaultValue": "Default", + "metadata": { + "description": "Optional. Specifies the mode of database creation." + } + }, + "elasticPoolResourceId": { "type": "string", - "defaultValue": "GeneralPurpose", + "nullable": true, "metadata": { - "description": "Optional. The skuTier or edition of the particular SKU." + "description": "Optional. The resource ID of the elastic pool containing this database." } }, - "skuName": { + "encryptionProtector": { "type": "string", - "defaultValue": "GP_Gen5_2", + "nullable": true, "metadata": { - "description": "Optional. The name of the SKU." + "description": "Optional. The azure key vault URI of the database if it's configured with per Database Customer Managed Keys." } }, - "skuCapacity": { - "type": "int", + "encryptionProtectorAutoRotation": { + "type": "bool", "nullable": true, "metadata": { - "description": "Optional. Capacity of the particular SKU." + "description": "Optional. The flag to enable or disable auto rotation of database encryption protector AKV key." } }, - "preferredEnclaveType": { + "federatedClientId": { + "type": "string", + "nullable": true, + "minLength": 36, + "maxLength": 36, + "metadata": { + "description": "Optional. The Client id used for cross tenant per database CMK scenario." + } + }, + "freeLimitExhaustionBehavior": { "type": "string", - "defaultValue": "", "allowedValues": [ - "", - "Default", - "VBS" + "AutoPause", + "BillOverUsage" ], + "nullable": true, "metadata": { - "description": "Optional. Type of enclave requested on the database i.e. Default or VBS enclaves." + "description": "Optional. Specifies the behavior when monthly free limits are exhausted for the free database." + } + }, + "highAvailabilityReplicaCount": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. The number of readonly secondary replicas associated with the database." + } + }, + "isLedgerOn": { + "type": "bool", + "defaultValue": false, + "metadata": { + "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." } }, - "skuFamily": { + "licenseType": { "type": "string", - "defaultValue": "", + "allowedValues": [ + "BasePrice", + "LicenseIncluded" + ], + "nullable": true, "metadata": { - "description": "Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here." + "description": "Optional. The license type to apply for this database." } }, - "skuSize": { + "longTermRetentionBackupResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, + "metadata": { + "description": "Optional. The resource identifier of the long term retention backup associated with create operation of this database." + } + }, + "maintenanceConfigurationId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur." + } + }, + "manualCutover": { + "type": "bool", + "nullable": true, "metadata": { - "description": "Optional. Size of the particular SKU." + "description": "Optional. Whether or not customer controlled manual cutover needs to be done during Update Database operation to Hyperscale tier." } }, "maxSizeBytes": { @@ -1110,176 +2292,176 @@ "description": "Optional. The max size of the database expressed in bytes." } }, - "sampleName": { + "minCapacity": { "type": "string", - "defaultValue": "", + "defaultValue": "0", "metadata": { - "description": "Optional. The name of the sample schema to apply when creating this database." + "description": "Optional. Minimal capacity that database will always have allocated." } }, - "zoneRedundant": { + "performCutover": { "type": "bool", - "defaultValue": true, + "nullable": true, "metadata": { - "description": "Optional. Whether or not this database is zone redundant." + "description": "Optional. To trigger customer controlled manual cutover during the wait state while Scaling operation is in progress." } }, - "licenseType": { + "preferredEnclaveType": { "type": "string", - "defaultValue": "", + "allowedValues": [ + "Default", + "VBS" + ], + "nullable": true, "metadata": { - "description": "Optional. The license type to apply for this database." + "description": "Optional. Type of enclave requested on the database i.e. Default or VBS enclaves." } }, "readScale": { "type": "string", - "defaultValue": "Disabled", "allowedValues": [ - "Enabled", - "Disabled" + "Disabled", + "Enabled" ], + "defaultValue": "Disabled", "metadata": { "description": "Optional. The state of read-only routing." } }, - "highAvailabilityReplicaCount": { - "type": "int", - "defaultValue": 0, - "metadata": { - "description": "Optional. The number of readonly secondary replicas associated with the database." - } - }, - "minCapacity": { + "recoverableDatabaseResourceId": { "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Minimal capacity that database will always have allocated." - } - }, - "autoPauseDelay": { - "type": "int", - "defaultValue": 0, + "nullable": true, "metadata": { - "description": "Optional. Time in minutes after which database is automatically paused. A value of -1 means that automatic pause is disabled." + "description": "Optional. The resource identifier of the recoverable database associated with create operation of this database." } }, - "tags": { - "type": "object", + "recoveryServicesRecoveryPointResourceId": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Tags of the resource." + "description": "Optional. The resource identifier of the recovery point associated with create operation of this database." } }, - "elasticPoolId": { + "requestedBackupStorageRedundancy": { "type": "string", - "defaultValue": "", + "allowedValues": [ + "Geo", + "GeoZone", + "Local", + "Zone" + ], + "defaultValue": "Local", "metadata": { - "description": "Optional. The resource ID of the elastic pool containing this database." + "description": "Optional. The storage account type to be used to store backups for this database." } }, - "location": { + "restorableDroppedDatabaseResourceId": { "type": "string", - "defaultValue": "[resourceGroup().location]", + "nullable": true, "metadata": { - "description": "Optional. Location for all resources." + "description": "Optional. The resource identifier of the restorable dropped database associated with create operation of this database." } }, - "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "restorePointInTime": { + "type": "string", + "nullable": true, "metadata": { - "description": "Optional. The diagnostic settings of the service." + "description": "Optional. Point in time (ISO8601 format) of the source database to restore when createMode set to Restore or PointInTimeRestore." } }, - "createMode": { + "sampleName": { "type": "string", - "defaultValue": "Default", - "allowedValues": [ - "Default", - "Copy", - "OnlineSecondary", - "PointInTimeRestore", - "Recovery", - "Restore", - "RestoreLongTermRetentionBackup", - "Secondary" - ], + "defaultValue": "", "metadata": { - "description": "Optional. Specifies the mode of database creation." + "description": "Optional. The name of the sample schema to apply when creating this database." } }, - "sourceDatabaseResourceId": { + "secondaryType": { "type": "string", - "defaultValue": "", + "allowedValues": [ + "Geo", + "Named", + "Standby" + ], + "nullable": true, "metadata": { - "description": "Optional. Resource ID of database if createMode set to Copy, Secondary, PointInTimeRestore, Recovery or Restore." + "description": "Optional. The secondary type of the database if it is a secondary." } }, "sourceDatabaseDeletionDate": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The time that the database was deleted when restoring a deleted database." } }, - "recoveryServicesRecoveryPointResourceId": { + "sourceDatabaseResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { - "description": "Optional. Resource ID of backup if createMode set to RestoreLongTermRetentionBackup." + "description": "Optional. The resource identifier of the source database associated with create operation of this database." } }, - "restorePointInTime": { + "sourceResourceId": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { - "description": "Optional. Point in time (ISO8601 format) of the source database to restore when createMode set to Restore or PointInTimeRestore." + "description": "Optional. The resource identifier of the source associated with the create operation of this database." } }, - "requestedBackupStorageRedundancy": { - "type": "string", - "defaultValue": "", - "allowedValues": [ - "Geo", - "Local", - "Zone", - "" - ], + "useFreeLimit": { + "type": "bool", + "nullable": true, "metadata": { - "description": "Optional. The storage account type to be used to store backups for this database." + "description": "Optional. Whether or not the database uses free monthly limits. Allowed on one database in a subscription." } }, - "isLedgerOn": { + "zoneRedundant": { "type": "bool", - "defaultValue": false, + "defaultValue": true, "metadata": { - "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." + "description": "Optional. Whether or not this database is zone redundant." } }, - "maintenanceConfigurationId": { + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "location": { "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "diagnosticSettings": { + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, "nullable": true, "metadata": { - "description": "Optional. Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur." + "description": "Optional. The diagnostic settings of the service." } }, "backupShortTermRetentionPolicy": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/shortTermBackupRetentionPolicyType", + "nullable": true, "metadata": { "description": "Optional. The short term backup retention policy to create for the database." } }, "backupLongTermRetentionPolicy": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/longTermBackupRetentionPolicyType", + "nullable": true, "metadata": { "description": "Optional. The long term backup retention policy to create for the database." } } }, - "variables": { - "skuVar": "[union(createObject('name', parameters('skuName'), 'tier', parameters('skuTier')), if(not(equals(parameters('skuCapacity'), null())), createObject('capacity', parameters('skuCapacity')), if(not(empty(parameters('skuFamily'))), createObject('family', parameters('skuFamily')), if(not(empty(parameters('skuSize'))), createObject('size', parameters('skuSize')), createObject()))))]" - }, "resources": { "server": { "existing": true, @@ -1293,28 +2475,42 @@ "name": "[format('{0}/{1}', parameters('serverName'), parameters('name'))]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", + "sku": "[parameters('sku')]", "properties": { - "preferredEnclaveType": "[if(not(empty(parameters('preferredEnclaveType'))), parameters('preferredEnclaveType'), null())]", - "collation": "[parameters('collation')]", - "maxSizeBytes": "[parameters('maxSizeBytes')]", - "sampleName": "[parameters('sampleName')]", - "zoneRedundant": "[parameters('zoneRedundant')]", - "licenseType": "[parameters('licenseType')]", - "readScale": "[parameters('readScale')]", - "minCapacity": "[if(not(empty(parameters('minCapacity'))), json(parameters('minCapacity')), 0)]", "autoPauseDelay": "[parameters('autoPauseDelay')]", + "availabilityZone": "[parameters('availabilityZone')]", + "catalogCollation": "[parameters('catalogCollation')]", + "collation": "[parameters('collation')]", + "createMode": "[parameters('createMode')]", + "elasticPoolId": "[parameters('elasticPoolResourceId')]", + "encryptionProtector": "[parameters('encryptionProtector')]", + "encryptionProtectorAutoRotation": "[parameters('encryptionProtectorAutoRotation')]", + "federatedClientId": "[parameters('federatedClientId')]", + "freeLimitExhaustionBehavior": "[parameters('freeLimitExhaustionBehavior')]", "highAvailabilityReplicaCount": "[parameters('highAvailabilityReplicaCount')]", - "requestedBackupStorageRedundancy": "[parameters('requestedBackupStorageRedundancy')]", "isLedgerOn": "[parameters('isLedgerOn')]", + "licenseType": "[parameters('licenseType')]", + "longTermRetentionBackupResourceId": "[parameters('longTermRetentionBackupResourceId')]", "maintenanceConfigurationId": "[parameters('maintenanceConfigurationId')]", - "elasticPoolId": "[parameters('elasticPoolId')]", - "createMode": "[parameters('createMode')]", - "sourceDatabaseId": "[if(not(empty(parameters('sourceDatabaseResourceId'))), parameters('sourceDatabaseResourceId'), null())]", - "sourceDatabaseDeletionDate": "[if(not(empty(parameters('sourceDatabaseDeletionDate'))), parameters('sourceDatabaseDeletionDate'), null())]", - "recoveryServicesRecoveryPointId": "[if(not(empty(parameters('recoveryServicesRecoveryPointResourceId'))), parameters('recoveryServicesRecoveryPointResourceId'), null())]", - "restorePointInTime": "[if(not(empty(parameters('restorePointInTime'))), parameters('restorePointInTime'), null())]" + "manualCutover": "[parameters('manualCutover')]", + "maxSizeBytes": "[parameters('maxSizeBytes')]", + "minCapacity": "[if(not(empty(parameters('minCapacity'))), json(parameters('minCapacity')), 0)]", + "performCutover": "[parameters('performCutover')]", + "preferredEnclaveType": "[parameters('preferredEnclaveType')]", + "readScale": "[parameters('readScale')]", + "recoverableDatabaseId": "[parameters('recoverableDatabaseResourceId')]", + "recoveryServicesRecoveryPointId": "[parameters('recoveryServicesRecoveryPointResourceId')]", + "requestedBackupStorageRedundancy": "[parameters('requestedBackupStorageRedundancy')]", + "restorableDroppedDatabaseId": "[parameters('restorableDroppedDatabaseResourceId')]", + "restorePointInTime": "[parameters('restorePointInTime')]", + "sampleName": "[parameters('sampleName')]", + "secondaryType": "[parameters('secondaryType')]", + "sourceDatabaseDeletionDate": "[parameters('sourceDatabaseDeletionDate')]", + "sourceDatabaseId": "[parameters('sourceDatabaseResourceId')]", + "sourceResourceId": "[parameters('sourceResourceId')]", + "useFreeLimit": "[parameters('useFreeLimit')]", + "zoneRedundant": "[parameters('zoneRedundant')]" }, - "sku": "[variables('skuVar')]", "dependsOn": [ "server" ] @@ -1361,6 +2557,7 @@ ] }, "database_backupShortTermRetentionPolicy": { + "condition": "[not(empty(parameters('backupShortTermRetentionPolicy')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-{1}-shBakRetPol', uniqueString(deployment().name, parameters('location')), parameters('name'))]", @@ -1377,10 +2574,10 @@ "value": "[parameters('name')]" }, "diffBackupIntervalInHours": { - "value": "[coalesce(tryGet(parameters('backupShortTermRetentionPolicy'), 'diffBackupIntervalInHours'), 24)]" + "value": "[tryGet(parameters('backupShortTermRetentionPolicy'), 'diffBackupIntervalInHours')]" }, "retentionDays": { - "value": "[coalesce(tryGet(parameters('backupShortTermRetentionPolicy'), 'retentionDays'), 7)]" + "value": "[tryGet(parameters('backupShortTermRetentionPolicy'), 'retentionDays')]" } }, "template": { @@ -1389,8 +2586,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "8635162595153731245" + "version": "0.30.23.60470", + "templateHash": "14890409200962565555" }, "name": "Azure SQL Server Database Short Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Short-Term Backup Retention Policy.", @@ -1413,7 +2610,7 @@ "type": "int", "defaultValue": 24, "metadata": { - "description": "Optional. Differential backup interval in hours." + "description": "Optional. Differential backup interval in hours. For Hyperscal tiers this value will be ignored." } }, "retentionDays": { @@ -1430,7 +2627,7 @@ "apiVersion": "2023-08-01-preview", "name": "[format('{0}/{1}/{2}', parameters('serverName'), parameters('databaseName'), 'default')]", "properties": { - "diffBackupIntervalInHours": "[parameters('diffBackupIntervalInHours')]", + "diffBackupIntervalInHours": "[if(equals(reference(resourceId('Microsoft.Sql/servers/databases', parameters('serverName'), parameters('databaseName')), '2023-08-01-preview', 'full').sku.tier, 'Hyperscale'), null(), parameters('diffBackupIntervalInHours'))]", "retentionDays": "[parameters('retentionDays')]" } } @@ -1465,6 +2662,7 @@ ] }, "database_backupLongTermRetentionPolicy": { + "condition": "[not(empty(parameters('backupLongTermRetentionPolicy')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-{1}-lgBakRetPol', uniqueString(deployment().name, parameters('location')), parameters('name'))]", @@ -1480,27 +2678,34 @@ "databaseName": { "value": "[parameters('name')]" }, + "backupStorageAccessTier": { + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'backupStorageAccessTier')]" + }, + "makeBackupsImmutable": { + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'makeBackupsImmutable')]" + }, "weeklyRetention": { - "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'weeklyRetention'), '')]" + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'weeklyRetention')]" }, "monthlyRetention": { - "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'monthlyRetention'), '')]" + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'monthlyRetention')]" }, "yearlyRetention": { - "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'yearlyRetention'), '')]" + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'yearlyRetention')]" }, "weekOfYear": { - "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'weekOfYear'), 1)]" + "value": "[tryGet(parameters('backupLongTermRetentionPolicy'), 'weekOfYear')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "2778016138108001251" + "version": "0.30.23.60470", + "templateHash": "841731129374883266" }, "name": "SQL Server Database Long Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Long-Term Backup Retention Policy.", @@ -1519,16 +2724,34 @@ "description": "Required. The name of the parent database." } }, - "weeklyRetention": { + "backupStorageAccessTier": { "type": "string", - "defaultValue": "", + "allowedValues": [ + "Archive", + "Hot" + ], + "nullable": true, "metadata": { - "description": "Optional. Monthly retention in ISO 8601 duration format." + "description": "Optional. The BackupStorageAccessTier for the LTR backups." + } + }, + "makeBackupsImmutable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The setting whether to make LTR backups immutable." } }, "monthlyRetention": { "type": "string", - "defaultValue": "", + "nullable": true, + "metadata": { + "description": "Optional. Monthly retention in ISO 8601 duration format." + } + }, + "weeklyRetention": { + "type": "string", + "nullable": true, "metadata": { "description": "Optional. Weekly retention in ISO 8601 duration format." } @@ -1542,25 +2765,45 @@ }, "yearlyRetention": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Yearly retention in ISO 8601 duration format." } } }, - "resources": [ - { - "type": "Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies", + "resources": { + "server::database": { + "existing": true, + "type": "Microsoft.Sql/servers/databases", + "apiVersion": "2023-08-01-preview", + "name": "[format('{0}/{1}', parameters('serverName'), parameters('databaseName'))]", + "dependsOn": [ + "server" + ] + }, + "server": { + "existing": true, + "type": "Microsoft.Sql/servers", "apiVersion": "2023-08-01-preview", + "name": "[parameters('serverName')]" + }, + "backupLongTermRetentionPolicy": { + "type": "Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies", + "apiVersion": "2023-05-01-preview", "name": "[format('{0}/{1}/{2}', parameters('serverName'), parameters('databaseName'), 'default')]", "properties": { + "backupStorageAccessTier": "[parameters('backupStorageAccessTier')]", + "makeBackupsImmutable": "[parameters('makeBackupsImmutable')]", "monthlyRetention": "[parameters('monthlyRetention')]", "weeklyRetention": "[parameters('weeklyRetention')]", "weekOfYear": "[parameters('weekOfYear')]", "yearlyRetention": "[parameters('yearlyRetention')]" - } + }, + "dependsOn": [ + "server::database" + ] } - ], + }, "outputs": { "resourceGroupName": { "type": "string", @@ -1642,50 +2885,50 @@ }, "mode": "Incremental", "parameters": { + "serverName": { + "value": "[parameters('name')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'tags'), parameters('tags'))]" + }, "name": { "value": "[parameters('elasticPools')[copyIndex()].name]" }, - "serverName": { - "value": "[parameters('name')]" + "sku": { + "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'sku')]" }, - "databaseMaxCapacity": { - "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'databaseMaxCapacity'), 2)]" + "autoPauseDelay": { + "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'autoPauseDelay')]" }, - "databaseMinCapacity": { - "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'databaseMinCapacity'), 0)]" + "availabilityZone": { + "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'availabilityZone')]" }, "highAvailabilityReplicaCount": { "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'highAvailabilityReplicaCount')]" }, "licenseType": { - "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'licenseType'), 'LicenseIncluded')]" + "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'licenseType')]" }, "maintenanceConfigurationId": { "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'maintenanceConfigurationId')]" }, "maxSizeBytes": { - "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'maxSizeBytes'), json('34359738368'))]" + "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'maxSizeBytes')]" }, "minCapacity": { "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'minCapacity')]" }, - "skuCapacity": { - "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'skuCapacity'), 2)]" - }, - "skuName": { - "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'skuName'), 'GP_Gen5')]" + "perDatabaseSettings": { + "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'perDatabaseSettings')]" }, - "skuTier": { - "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'skuTier'), 'GeneralPurpose')]" + "preferredEnclaveType": { + "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'preferredEnclaveType')]" }, "zoneRedundant": { - "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'zoneRedundant'), true())]" - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'tags'), parameters('tags'))]" + "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'zoneRedundant')]" } }, "template": { @@ -1695,13 +2938,100 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17774091526328280898" + "version": "0.30.23.60470", + "templateHash": "10024079638382167120" }, "name": "SQL Server Elastic Pool", "description": "This module deploys an Azure SQL Server Elastic Pool.", "owner": "Azure/module-maintainers" }, + "definitions": { + "elasticPoolPerDatabaseSettingsType": { + "type": "object", + "properties": { + "autoPauseDelay": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Auto Pause Delay for per database within pool." + } + }, + "maxCapacity": { + "type": "string", + "metadata": { + "description": "Required. The maximum capacity any one database can consume. Examples: '0.5', '2'." + } + }, + "minCapacity": { + "type": "string", + "metadata": { + "description": "Required. The minimum capacity all databases are guaranteed. Examples: '0.5', '1'." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The per database settings for the elastic pool." + } + }, + "elasticPoolSkuType": { + "type": "object", + "properties": { + "capacity": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The capacity of the particular SKU." + } + }, + "family": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here." + } + }, + "name": { + "type": "string", + "allowedValues": [ + "BC_DC", + "BC_Gen5", + "BasicPool", + "GP_DC", + "GP_FSv2", + "GP_Gen5", + "HS_Gen5", + "HS_MOPRMS", + "HS_PRMS", + "PremiumPool", + "ServerlessPool", + "StandardPool" + ], + "metadata": { + "description": "Required. The name of the SKU, typically, a letter + Number code, e.g. P3." + } + }, + "size": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Size of the particular SKU." + } + }, + "tier": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tier or edition of the particular SKU, e.g. Basic, Premium." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The elastic pool SKU." + } + } + }, "parameters": { "name": { "type": "string", @@ -1729,25 +3059,35 @@ "description": "Optional. Location for all resources." } }, - "skuCapacity": { - "type": "int", - "defaultValue": 2, + "sku": { + "$ref": "#/definitions/elasticPoolSkuType", + "defaultValue": { + "capacity": 2, + "name": "GP_Gen5", + "tier": "GeneralPurpose" + }, "metadata": { - "description": "Optional. Capacity of the particular SKU." + "description": "Optional. The elastic pool SKU." } }, - "skuName": { - "type": "string", - "defaultValue": "GP_Gen5", + "autoPauseDelay": { + "type": "int", + "defaultValue": -1, "metadata": { - "description": "Optional. The name of the SKU, typically, a letter + Number code, e.g. P3." + "description": "Optional. Time in minutes after which elastic pool is automatically paused. A value of -1 means that automatic pause is disabled." } }, - "skuTier": { + "availabilityZone": { "type": "string", - "defaultValue": "GeneralPurpose", + "allowedValues": [ + "1", + "2", + "3", + "NoPreference" + ], + "defaultValue": "NoPreference", "metadata": { - "description": "Optional. The tier or edition of the particular SKU, e.g. Basic, Premium." + "description": "Optional. Specifies the availability zone the pool's primary replica is pinned to." } }, "highAvailabilityReplicaCount": { @@ -1789,18 +3129,26 @@ "description": "Optional. Minimal capacity that serverless pool will not shrink below, if not paused." } }, - "databaseMaxCapacity": { - "type": "int", - "defaultValue": 2, + "perDatabaseSettings": { + "$ref": "#/definitions/elasticPoolPerDatabaseSettingsType", + "defaultValue": { + "autoPauseDelay": -1, + "maxCapacity": "2", + "minCapacity": "0" + }, "metadata": { - "description": "Optional. The maximum capacity any one database can consume." + "description": "Optional. The per database settings for the elastic pool." } }, - "databaseMinCapacity": { - "type": "int", - "defaultValue": 0, + "preferredEnclaveType": { + "type": "string", + "allowedValues": [ + "Default", + "VBS" + ], + "defaultValue": "Default", "metadata": { - "description": "Optional. The minimum capacity all databases are guaranteed." + "description": "Optional. Type of enclave requested on the elastic pool." } }, "zoneRedundant": { @@ -1824,21 +3172,17 @@ "name": "[format('{0}/{1}', parameters('serverName'), parameters('name'))]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", - "sku": { - "capacity": "[parameters('skuCapacity')]", - "name": "[parameters('skuName')]", - "tier": "[parameters('skuTier')]" - }, + "sku": "[parameters('sku')]", "properties": { + "autoPauseDelay": "[parameters('autoPauseDelay')]", + "availabilityZone": "[parameters('availabilityZone')]", "highAvailabilityReplicaCount": "[parameters('highAvailabilityReplicaCount')]", "licenseType": "[parameters('licenseType')]", "maintenanceConfigurationId": "[parameters('maintenanceConfigurationId')]", "maxSizeBytes": "[parameters('maxSizeBytes')]", "minCapacity": "[parameters('minCapacity')]", - "perDatabaseSettings": { - "minCapacity": "[parameters('databaseMinCapacity')]", - "maxCapacity": "[parameters('databaseMaxCapacity')]" - }, + "perDatabaseSettings": "[if(not(empty(parameters('perDatabaseSettings'))), createObject('autoPauseDelay', tryGet(parameters('perDatabaseSettings'), 'autoPauseDelay'), 'maxCapacity', json(tryGet(parameters('perDatabaseSettings'), 'maxCapacity')), 'minCapacity', json(tryGet(parameters('perDatabaseSettings'), 'minCapacity'))), null())]", + "preferredEnclaveType": "[parameters('preferredEnclaveType')]", "zoneRedundant": "[parameters('zoneRedundant')]" }, "dependsOn": [ @@ -2681,8 +4025,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7779473510493338097" + "version": "0.30.23.60470", + "templateHash": "6449556555046717103" }, "name": "Azure SQL Server Firewall Rule", "description": "This module deploys an Azure SQL Server Firewall Rule.", @@ -2789,8 +4133,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7859066741604114060" + "version": "0.30.23.60470", + "templateHash": "4969955763304077350" }, "name": "Azure SQL Server Virtual Network Rules", "description": "This module deploys an Azure SQL Server Virtual Network Rule.", @@ -2911,8 +4255,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6025191760768766090" + "version": "0.30.23.60470", + "templateHash": "15406914222375641032" }, "name": "Azure SQL Server Security Alert Policies", "description": "This module deploys an Azure SQL Server Security Alert Policy.", @@ -3072,8 +4416,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5682596516926040129" + "version": "0.30.23.60470", + "templateHash": "11004049200994426011" }, "name": "Azure SQL Server Vulnerability Assessments", "description": "This module deploys an Azure SQL Server Vulnerability Assessment.", @@ -3175,8 +4519,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17251889896692066430" + "version": "0.30.23.60470", + "templateHash": "13956215614091387428" } }, "parameters": { @@ -3268,8 +4612,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5863771213375512760" + "version": "0.30.23.60470", + "templateHash": "17839617504395216689" }, "name": "Azure SQL Server Keys", "description": "This module deploys an Azure SQL Server Key.", @@ -3391,8 +4735,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6914924378490463775" + "version": "0.30.23.60470", + "templateHash": "11473914706327458055" }, "name": "Azure SQL Server Encryption Protector", "description": "This module deploys an Azure SQL Server Encryption Protector.", @@ -3473,7 +4817,7 @@ ] }, "server_audit_settings": { - "condition": "[not(empty(parameters('auditSettings')))]", + "condition": "[not(equals(parameters('auditSettings'), null()))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-Sql-AuditSettings', uniqueString(deployment().name, parameters('location')))]", @@ -3490,28 +4834,28 @@ "value": "[coalesce(tryGet(parameters('auditSettings'), 'name'), 'default')]" }, "state": { - "value": "[coalesce(tryGet(parameters('auditSettings'), 'state'), 'Disabled')]" + "value": "[tryGet(parameters('auditSettings'), 'state')]" }, "auditActionsAndGroups": { - "value": "[coalesce(tryGet(parameters('auditSettings'), 'auditActionsAndGroups'), createArray('BATCH_COMPLETED_GROUP', 'SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP', 'FAILED_DATABASE_AUTHENTICATION_GROUP'))]" + "value": "[tryGet(parameters('auditSettings'), 'auditActionsAndGroups')]" }, "isAzureMonitorTargetEnabled": { - "value": "[coalesce(tryGet(parameters('auditSettings'), 'isAzureMonitorTargetEnabled'), false())]" + "value": "[tryGet(parameters('auditSettings'), 'isAzureMonitorTargetEnabled')]" }, "isDevopsAuditEnabled": { - "value": "[coalesce(tryGet(parameters('auditSettings'), 'isDevopsAuditEnabled'), false())]" + "value": "[tryGet(parameters('auditSettings'), 'isDevopsAuditEnabled')]" }, "isManagedIdentityInUse": { - "value": "[coalesce(tryGet(parameters('auditSettings'), 'isManagedIdentityInUse'), false())]" + "value": "[tryGet(parameters('auditSettings'), 'isManagedIdentityInUse')]" }, "isStorageSecondaryKeyInUse": { - "value": "[coalesce(tryGet(parameters('auditSettings'), 'isStorageSecondaryKeyInUse'), false())]" + "value": "[tryGet(parameters('auditSettings'), 'isStorageSecondaryKeyInUse')]" }, "queueDelayMs": { - "value": "[coalesce(tryGet(parameters('auditSettings'), 'queueDelayMs'), 1000)]" + "value": "[tryGet(parameters('auditSettings'), 'queueDelayMs')]" }, "retentionDays": { - "value": "[coalesce(tryGet(parameters('auditSettings'), 'retentionDays'), 90)]" + "value": "[tryGet(parameters('auditSettings'), 'retentionDays')]" }, "storageAccountResourceId": { "value": "[tryGet(parameters('auditSettings'), 'storageAccountResourceId')]" @@ -3524,8 +4868,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4165841300638093382" + "version": "0.30.23.60470", + "templateHash": "6303070680265885029" }, "name": "Azure SQL Server Audit Settings", "description": "This module deploys an Azure SQL Server Audit Settings.", @@ -3546,31 +4890,39 @@ }, "state": { "type": "string", + "defaultValue": "Enabled", "allowedValues": [ "Enabled", "Disabled" ], "metadata": { - "description": "Required. The resource group of the SQL Server. Required if the template is used in a standalone deployment." + "description": "Optional. Specifies the state of the audit. If state is Enabled, storageEndpoint or isAzureMonitorTargetEnabled are required." } }, "auditActionsAndGroups": { "type": "array", - "nullable": true, + "items": { + "type": "string" + }, + "defaultValue": [ + "BATCH_COMPLETED_GROUP", + "SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP", + "FAILED_DATABASE_AUTHENTICATION_GROUP" + ], "metadata": { "description": "Optional. Specifies the Actions-Groups and Actions to audit." } }, "isAzureMonitorTargetEnabled": { "type": "bool", - "defaultValue": false, + "defaultValue": true, "metadata": { "description": "Optional. Specifies whether audit events are sent to Azure Monitor." } }, "isDevopsAuditEnabled": { "type": "bool", - "nullable": true, + "defaultValue": false, "metadata": { "description": "Optional. Specifies the state of devops audit. If state is Enabled, devops logs will be sent to Azure Monitor." } @@ -3584,21 +4936,21 @@ }, "isStorageSecondaryKeyInUse": { "type": "bool", - "nullable": true, + "defaultValue": false, "metadata": { "description": "Optional. Specifies whether storageAccountAccessKey value is the storage's secondary key." } }, "queueDelayMs": { "type": "int", - "nullable": true, + "defaultValue": 1000, "metadata": { "description": "Optional. Specifies the amount of time in milliseconds that can elapse before audit actions are forced to be processed." } }, "retentionDays": { "type": "int", - "nullable": true, + "defaultValue": 90, "metadata": { "description": "Optional. Specifies the number of days to keep in the audit logs in the storage account." } @@ -3663,8 +5015,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17251889896692066430" + "version": "0.30.23.60470", + "templateHash": "13956215614091387428" } }, "parameters": { @@ -3751,12 +5103,12 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "594547303316002116" + "version": "0.30.23.60470", + "templateHash": "13150358169332921706" } }, "definitions": { - "secretSetType": { + "secretSetOutputType": { "type": "object", "properties": { "secretResourceId": { @@ -3770,10 +5122,19 @@ "metadata": { "description": "The secret URI of the exported secret." } + }, + "secretUriWithVersion": { + "type": "string", + "metadata": { + "description": "The secret URI with version of the exported secret." + } } }, "metadata": { - "__bicep_export!": true + "description": "An AVM-aligned type for the output of the secret set via the secrets export feature.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } } }, "secretToSetType": { @@ -3791,6 +5152,12 @@ "description": "Required. The value of the secret to set." } } + }, + "metadata": { + "description": "An AVM-aligned type for the secret to set via the secrets export feature.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } } } }, @@ -3838,7 +5205,7 @@ "secretsSet": { "type": "array", "items": { - "$ref": "#/definitions/secretSetType" + "$ref": "#/definitions/secretSetOutputType" }, "metadata": { "description": "The references to the secrets exported to the provided Key Vault." @@ -3847,7 +5214,8 @@ "count": "[length(range(0, length(coalesce(parameters('secretsToSet'), createArray()))))]", "input": { "secretResourceId": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('secretsToSet')[range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()]].name)]", - "secretUri": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUri]" + "secretUri": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUri]", + "secretUriWithVersion": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUriWithVersion]" } } } diff --git a/avm/res/sql/server/modules/keyVaultExport.bicep b/avm/res/sql/server/modules/keyVaultExport.bicep index c4ff7c2f9d..61c84e06a2 100644 --- a/avm/res/sql/server/modules/keyVaultExport.bicep +++ b/avm/res/sql/server/modules/keyVaultExport.bicep @@ -5,6 +5,7 @@ @description('Required. The name of the Key Vault to set the secrets in.') param keyVaultName string +import { secretToSetType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Required. The secrets to set in the Key Vault.') param secretsToSet secretToSetType[] @@ -30,33 +31,13 @@ resource secrets 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = [ // Outputs // // =========== // +import { secretSetOutputType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('The references to the secrets exported to the provided Key Vault.') -output secretsSet secretSetType[] = [ +output secretsSet secretSetOutputType[] = [ #disable-next-line outputs-should-not-contain-secrets // Only returning the references, not a secret value for index in range(0, length(secretsToSet ?? [])): { secretResourceId: secrets[index].id secretUri: secrets[index].properties.secretUri + secretUriWithVersion: secrets[index].properties.secretUriWithVersion } ] - -// =============== // -// Definitions // -// =============== // - -@export() -type secretSetType = { - @description('The resourceId of the exported secret.') - secretResourceId: string - - @description('The secret URI of the exported secret.') - secretUri: string -} - -type secretToSetType = { - @description('Required. The name of the secret to set.') - name: string - - @description('Required. The value of the secret to set.') - @secure() - value: string -} diff --git a/avm/res/sql/server/security-alert-policy/main.json b/avm/res/sql/server/security-alert-policy/main.json index 8ac3df6310..08cdceaee6 100644 --- a/avm/res/sql/server/security-alert-policy/main.json +++ b/avm/res/sql/server/security-alert-policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6025191760768766090" + "version": "0.30.23.60470", + "templateHash": "15406914222375641032" }, "name": "Azure SQL Server Security Alert Policies", "description": "This module deploys an Azure SQL Server Security Alert Policy.", diff --git a/avm/res/sql/server/tests/e2e/elasticPool/main.test.bicep b/avm/res/sql/server/tests/e2e/elasticPool/main.test.bicep new file mode 100644 index 0000000000..9202a2fe6c --- /dev/null +++ b/avm/res/sql/server/tests/e2e/elasticPool/main.test.bicep @@ -0,0 +1,73 @@ +targetScope = 'subscription' + +metadata name = 'Using elastic pool' +metadata description = 'This instance deploys the module with an elastic pool.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-sql.servers-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'ssep' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + administratorLogin: 'adminUserName' + administratorLoginPassword: password + elasticPools: [ + // bare minimum elastic pool: only a name is specified + { + name: '${namePrefix}-${serviceShort}-ep-001' + } + // more complex elastic pool with non-default SKU and per database settings + { + name: '${namePrefix}-${serviceShort}-ep-002' + sku: { + name: 'GP_Gen5' + tier: 'GeneralPurpose' + capacity: 4 + } + perDatabaseSettings: { + minCapacity: '0.5' + maxCapacity: '4' + } + } + ] + } + } +] diff --git a/avm/res/sql/server/tests/e2e/max/dependencies.bicep b/avm/res/sql/server/tests/e2e/max/dependencies.bicep index f2797af2b7..7bea7face2 100644 --- a/avm/res/sql/server/tests/e2e/max/dependencies.bicep +++ b/avm/res/sql/server/tests/e2e/max/dependencies.bicep @@ -60,7 +60,7 @@ resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { name: 'standard' } tenantId: tenant().tenantId - enablePurgeProtection: null + enablePurgeProtection: true // Required for encryption to work enabledForTemplateDeployment: true enabledForDiskEncryption: true enabledForDeployment: true diff --git a/avm/res/sql/server/tests/e2e/max/main.test.bicep b/avm/res/sql/server/tests/e2e/max/main.test.bicep index e95f51ae35..232c88c9cb 100644 --- a/avm/res/sql/server/tests/e2e/max/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/max/main.test.bicep @@ -25,6 +25,9 @@ param password string = newGuid() @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + // ============ // // Dependencies // // ============ // @@ -40,7 +43,8 @@ module nestedDependencies 'dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' params: { - keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' location: enforcedLocation @@ -113,18 +117,22 @@ module testDeployment '../../../main.bicep' = { elasticPools: [ { name: '${namePrefix}-${serviceShort}-ep-001' - skuName: 'GP_Gen5' - skuTier: 'GeneralPurpose' - skuCapacity: 10 + sku: { + name: 'GP_Gen5' + tier: 'GeneralPurpose' + capacity: 10 + } } ] databases: [ { name: '${namePrefix}-${serviceShort}db-001' collation: 'SQL_Latin1_General_CP1_CI_AS' - skuTier: 'GeneralPurpose' - skuName: 'ElasticPool' - skuCapacity: 0 + sku: { + name: 'ElasticPool' + tier: 'GeneralPurpose' + capacity: 0 + } maxSizeBytes: 34359738368 licenseType: 'LicenseIncluded' diagnosticSettings: [ @@ -136,11 +144,7 @@ module testDeployment '../../../main.bicep' = { workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } ] - elasticPoolId: '${resourceGroup.id}/providers/Microsoft.Sql/servers/${namePrefix}-${serviceShort}/elasticPools/${namePrefix}-${serviceShort}-ep-001' - encryptionProtectorObj: { - serverKeyType: 'AzureKeyVault' - serverKeyName: '${nestedDependencies.outputs.keyVaultName}_${nestedDependencies.outputs.keyVaultKeyName}_${last(split(nestedDependencies.outputs.keyVaultEncryptionKeyUrl, '/'))}' - } + elasticPoolResourceId: '${resourceGroup.id}/providers/Microsoft.Sql/servers/${namePrefix}-${serviceShort}/elasticPools/${namePrefix}-${serviceShort}-ep-001' backupShortTermRetentionPolicy: { retentionDays: 14 } @@ -149,6 +153,10 @@ module testDeployment '../../../main.bicep' = { } } ] + encryptionProtectorObj: { + serverKeyType: 'AzureKeyVault' + serverKeyName: '${nestedDependencies.outputs.keyVaultName}_${nestedDependencies.outputs.keyVaultKeyName}_${last(split(nestedDependencies.outputs.keyVaultEncryptionKeyUrl, '/'))}' + } firewallRules: [ { name: 'AllowAllWindowsAzureIps' diff --git a/avm/res/sql/server/tests/e2e/secondary/main.test.bicep b/avm/res/sql/server/tests/e2e/secondary/main.test.bicep index d86a8377b4..d2b8cfab0f 100644 --- a/avm/res/sql/server/tests/e2e/secondary/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/secondary/main.test.bicep @@ -59,8 +59,10 @@ module testDeployment '../../../main.bicep' = { databases: [ { name: nestedDependencies.outputs.databaseName - skuTier: 'Basic' - skuName: 'Basic' + sku: { + name: 'Basic' + tier: 'Basic' + } maxSizeBytes: 2147483648 createMode: 'Secondary' sourceDatabaseResourceId: nestedDependencies.outputs.databaseResourceId diff --git a/avm/res/sql/server/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/sql/server/tests/e2e/waf-aligned/dependencies.bicep index f2797af2b7..7bea7face2 100644 --- a/avm/res/sql/server/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/sql/server/tests/e2e/waf-aligned/dependencies.bicep @@ -60,7 +60,7 @@ resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { name: 'standard' } tenantId: tenant().tenantId - enablePurgeProtection: null + enablePurgeProtection: true // Required for encryption to work enabledForTemplateDeployment: true enabledForDiskEncryption: true enabledForDeployment: true diff --git a/avm/res/sql/server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/sql/server/tests/e2e/waf-aligned/main.test.bicep index 3777c51c2c..a8da430a58 100644 --- a/avm/res/sql/server/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/waf-aligned/main.test.bicep @@ -21,6 +21,9 @@ param serviceShort string = 'sqlswaf' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + // ============ // // Dependencies // // ============ // @@ -36,7 +39,8 @@ module nestedDependencies 'dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' params: { - keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' location: enforcedLocation @@ -88,9 +92,11 @@ module testDeployment '../../../main.bicep' = { elasticPools: [ { name: '${namePrefix}-${serviceShort}-ep-001' - skuName: 'GP_Gen5' - skuTier: 'GeneralPurpose' - skuCapacity: 10 + sku: { + name: 'GP_Gen5' + tier: 'GeneralPurpose' + capacity: 10 + } maintenanceConfigurationId: '${subscription().id}/providers/Microsoft.Maintenance/publicMaintenanceConfigurations/SQL_${enforcedLocation}_DB_1' } ] @@ -98,9 +104,11 @@ module testDeployment '../../../main.bicep' = { { name: '${namePrefix}-${serviceShort}db-001' collation: 'SQL_Latin1_General_CP1_CI_AS' - skuTier: 'GeneralPurpose' - skuName: 'ElasticPool' - skuCapacity: 0 + sku: { + name: 'ElasticPool' + tier: 'GeneralPurpose' + capacity: 0 + } maxSizeBytes: 34359738368 licenseType: 'LicenseIncluded' diagnosticSettings: [ @@ -112,11 +120,7 @@ module testDeployment '../../../main.bicep' = { workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } ] - elasticPoolId: '${resourceGroup.id}/providers/Microsoft.Sql/servers/${namePrefix}-${serviceShort}/elasticPools/${namePrefix}-${serviceShort}-ep-001' - encryptionProtectorObj: { - serverKeyType: 'AzureKeyVault' - serverKeyName: '${nestedDependencies.outputs.keyVaultName}_${nestedDependencies.outputs.keyVaultKeyName}_${last(split(nestedDependencies.outputs.keyVaultEncryptionKeyUrl, '/'))}' - } + elasticPoolResourceId: '${resourceGroup.id}/providers/Microsoft.Sql/servers/${namePrefix}-${serviceShort}/elasticPools/${namePrefix}-${serviceShort}-ep-001' backupShortTermRetentionPolicy: { retentionDays: 14 } @@ -125,6 +129,10 @@ module testDeployment '../../../main.bicep' = { } } ] + encryptionProtectorObj: { + serverKeyType: 'AzureKeyVault' + serverKeyName: '${nestedDependencies.outputs.keyVaultName}_${nestedDependencies.outputs.keyVaultKeyName}_${last(split(nestedDependencies.outputs.keyVaultEncryptionKeyUrl, '/'))}' + } securityAlertPolicies: [ { name: 'Default' diff --git a/avm/res/sql/server/version.json b/avm/res/sql/server/version.json index b8b30a0125..9c08aae215 100644 --- a/avm/res/sql/server/version.json +++ b/avm/res/sql/server/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.9", + "version": "0.10", "pathFilters": [ "./main.json" ] diff --git a/avm/res/sql/server/virtual-network-rule/main.json b/avm/res/sql/server/virtual-network-rule/main.json index 6e94f437e0..8aeb38250b 100644 --- a/avm/res/sql/server/virtual-network-rule/main.json +++ b/avm/res/sql/server/virtual-network-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7859066741604114060" + "version": "0.30.23.60470", + "templateHash": "4969955763304077350" }, "name": "Azure SQL Server Virtual Network Rules", "description": "This module deploys an Azure SQL Server Virtual Network Rule.", diff --git a/avm/res/sql/server/vulnerability-assessment/main.json b/avm/res/sql/server/vulnerability-assessment/main.json index 431b5c318c..134adac324 100644 --- a/avm/res/sql/server/vulnerability-assessment/main.json +++ b/avm/res/sql/server/vulnerability-assessment/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "5682596516926040129" + "version": "0.30.23.60470", + "templateHash": "11004049200994426011" }, "name": "Azure SQL Server Vulnerability Assessments", "description": "This module deploys an Azure SQL Server Vulnerability Assessment.", @@ -107,8 +107,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "17251889896692066430" + "version": "0.30.23.60470", + "templateHash": "13956215614091387428" } }, "parameters": { diff --git a/avm/res/storage/storage-account/README.md b/avm/res/storage/storage-account/README.md index b5105ee977..607e1004b9 100644 --- a/avm/res/storage/storage-account/README.md +++ b/avm/res/storage/storage-account/README.md @@ -500,13 +500,11 @@ module storageAccount 'br/public:avm/res/storage/storage-account:' = { } { allowProtectedAppendWrites: false - enableWORM: true metadata: { testKey: 'testValue' } name: 'archivecontainer' publicAccess: 'None' - WORMRetention: 666 } ] deleteRetentionPolicyDays: 9 @@ -945,13 +943,11 @@ module storageAccount 'br/public:avm/res/storage/storage-account:' = { }, { "allowProtectedAppendWrites": false, - "enableWORM": true, "metadata": { "testKey": "testValue" }, "name": "archivecontainer", - "publicAccess": "None", - "WORMRetention": 666 + "publicAccess": "None" } ], "deleteRetentionPolicyDays": 9, @@ -1424,13 +1420,11 @@ param blobServices = { } { allowProtectedAppendWrites: false - enableWORM: true metadata: { testKey: 'testValue' } name: 'archivecontainer' publicAccess: 'None' - WORMRetention: 666 } ] deleteRetentionPolicyDays: 9 @@ -2353,13 +2347,11 @@ module storageAccount 'br/public:avm/res/storage/storage-account:' = { } { allowProtectedAppendWrites: false - enableWORM: true metadata: { testKey: 'testValue' } name: 'archivecontainer' publicAccess: 'None' - WORMRetention: 666 } ] deleteRetentionPolicyDays: 9 @@ -2616,13 +2608,11 @@ module storageAccount 'br/public:avm/res/storage/storage-account:' = { }, { "allowProtectedAppendWrites": false, - "enableWORM": true, "metadata": { "testKey": "testValue" }, "name": "archivecontainer", - "publicAccess": "None", - "WORMRetention": 666 + "publicAccess": "None" } ], "deleteRetentionPolicyDays": 9, @@ -2909,13 +2899,11 @@ param blobServices = { } { allowProtectedAppendWrites: false - enableWORM: true metadata: { testKey: 'testValue' } name: 'archivecontainer' publicAccess: 'None' - WORMRetention: 666 } ] deleteRetentionPolicyDays: 9 @@ -3319,7 +3307,7 @@ The customer managed key definition. | Parameter | Type | Description | | :-- | :-- | :-- | | [`keyVersion`](#parameter-customermanagedkeykeyversion) | string | The version of the customer managed key to reference for encryption. If not provided, using 'latest'. | -| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeyuserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. If used must also be specified in `managedIdentities.userAssignedResourceIds`. Required if no system assigned identity is available for use. | +| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeyuserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. | ### Parameter: `customerManagedKey.keyName` @@ -3344,7 +3332,7 @@ The version of the customer managed key to reference for encryption. If not prov ### Parameter: `customerManagedKey.userAssignedIdentityResourceId` -User assigned identity to use when fetching the customer managed key. If used must also be specified in `managedIdentities.userAssignedResourceIds`. Required if no system assigned identity is available for use. +User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. - Required: No - Type: string @@ -3371,9 +3359,10 @@ The diagnostic settings of the service. | [`eventHubAuthorizationRuleResourceId`](#parameter-diagnosticsettingseventhubauthorizationruleresourceid) | 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. | | [`eventHubName`](#parameter-diagnosticsettingseventhubname) | 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. | | [`logAnalyticsDestinationType`](#parameter-diagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | +| [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | -| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -3405,6 +3394,42 @@ A string indicating whether the export to Log Analytics should use the default d ] ``` +### Parameter: `diagnosticSettings.logCategoriesAndGroups` + +The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`category`](#parameter-diagnosticsettingslogcategoriesandgroupscategory) | string | Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here. | +| [`categoryGroup`](#parameter-diagnosticsettingslogcategoriesandgroupscategorygroup) | string | Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs. | +| [`enabled`](#parameter-diagnosticsettingslogcategoriesandgroupsenabled) | bool | Enable or disable the category explicitly. Default is `true`. | + +### Parameter: `diagnosticSettings.logCategoriesAndGroups.category` + +Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.logCategoriesAndGroups.categoryGroup` + +Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.logCategoriesAndGroups.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + ### Parameter: `diagnosticSettings.marketplacePartnerResourceId` The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. @@ -3414,7 +3439,7 @@ The full ARM resource ID of the Marketplace resource to which you would like to ### Parameter: `diagnosticSettings.metricCategories` -The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. +The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. - Required: No - Type: array @@ -3447,7 +3472,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -3633,7 +3658,7 @@ The managed identity definition for this resource. | Parameter | Type | Description | | :-- | :-- | :-- | | [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | ### Parameter: `managedIdentities.systemAssigned` @@ -3644,7 +3669,7 @@ Enables system assigned managed identity on the resource. ### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. - Required: No - Type: array @@ -3775,7 +3800,7 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file" for a Storage Account's Private Endpoints. | | [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | **Optional parameters** @@ -3800,7 +3825,7 @@ Configuration details for private endpoints. For security reasons, it is recomme ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". +The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file" for a Storage Account's Private Endpoints. - Required: Yes - Type: string @@ -3830,23 +3855,28 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint ip address. | -| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private ip addresses of the private endpoint. | - -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` +| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -Fqdn that resolves to private endpoint ip address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` -A list of private ip addresses of the private endpoint. +A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -3895,7 +3925,7 @@ Properties of private endpoint IP configurations. | :-- | :-- | :-- | | [`groupId`](#parameter-privateendpointsipconfigurationspropertiesgroupid) | string | The ID of a group obtained from the remote resource that this private endpoint should connect to. | | [`memberName`](#parameter-privateendpointsipconfigurationspropertiesmembername) | string | The member name of a group obtained from the remote resource that this private endpoint should connect to. | -| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | string | A private ip address obtained from the private endpoint's subnet. | +| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | string | A private IP address obtained from the private endpoint's subnet. | ### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` @@ -3913,7 +3943,7 @@ The member name of a group obtained from the remote resource that this private e ### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` -A private ip address obtained from the private endpoint's subnet. +A private IP address obtained from the private endpoint's subnet. - Required: Yes - Type: string @@ -3993,7 +4023,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -4003,7 +4033,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -4018,7 +4048,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -4029,7 +4059,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -4454,6 +4484,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Notes diff --git a/avm/res/storage/storage-account/blob-service/README.md b/avm/res/storage/storage-account/blob-service/README.md index 80fadec93f..464c506615 100644 --- a/avm/res/storage/storage-account/blob-service/README.md +++ b/avm/res/storage/storage-account/blob-service/README.md @@ -7,6 +7,7 @@ This module deploys a Storage Account Blob Service. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -164,8 +165,8 @@ The diagnostic settings of the service. | [`logAnalyticsDestinationType`](#parameter-diagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | -| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -242,7 +243,7 @@ The full ARM resource ID of the Marketplace resource to which you would like to ### Parameter: `diagnosticSettings.metricCategories` -The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. +The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. - Required: No - Type: array @@ -275,7 +276,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -333,3 +334,11 @@ The blob service properties for blob restore policy. If point-in-time restore is | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/storage/storage-account/blob-service/container/README.md b/avm/res/storage/storage-account/blob-service/container/README.md index 34d861e3b5..f90db350e2 100644 --- a/avm/res/storage/storage-account/blob-service/container/README.md +++ b/avm/res/storage/storage-account/blob-service/container/README.md @@ -7,6 +7,7 @@ This module deploys a Storage Account Blob Container. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -265,3 +266,11 @@ The principal type of the assigned principal ID. | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/storage/storage-account/blob-service/container/main.bicep b/avm/res/storage/storage-account/blob-service/container/main.bicep index 9a19a6096f..78e7133d90 100644 --- a/avm/res/storage/storage-account/blob-service/container/main.bicep +++ b/avm/res/storage/storage-account/blob-service/container/main.bicep @@ -44,8 +44,9 @@ param metadata object = {} @description('Optional. Specifies whether data in the container may be accessed publicly and the level of access.') param publicAccess string = 'None' +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -165,33 +166,3 @@ output resourceId string = container.id @description('The resource group of the deployed container.') output resourceGroupName string = resourceGroup().name - -// =============== // -// Definitions // -// =============== // - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/storage/storage-account/blob-service/container/main.json b/avm/res/storage/storage-account/blob-service/container/main.json index 1144d31c91..46555744ca 100644 --- a/avm/res/storage/storage-account/blob-service/container/main.json +++ b/avm/res/storage/storage-account/blob-service/container/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "7740343838101895320" + "templateHash": "2340678191837281561" }, "name": "Storage Account Blob Containers", "description": "This module deploys a Storage Account Blob Container.", @@ -14,77 +14,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -177,7 +179,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/storage/storage-account/blob-service/main.bicep b/avm/res/storage/storage-account/blob-service/main.bicep index bb43c4d610..29ea2c950e 100644 --- a/avm/res/storage/storage-account/blob-service/main.bicep +++ b/avm/res/storage/storage-account/blob-service/main.bicep @@ -61,8 +61,9 @@ param restorePolicyDays int = 6 @description('Optional. Blob containers to create.') param containers array? +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? // The name of the blob services var name = 'default' @@ -172,51 +173,3 @@ output resourceId string = blobServices.id @description('The name of the deployed blob service.') output resourceGroupName string = resourceGroup().name - -// =============== // -// Definitions // -// =============== // - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? diff --git a/avm/res/storage/storage-account/blob-service/main.json b/avm/res/storage/storage-account/blob-service/main.json index 6ab964fa85..6bd0d12cc4 100644 --- a/avm/res/storage/storage-account/blob-service/main.json +++ b/avm/res/storage/storage-account/blob-service/main.json @@ -6,132 +6,134 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "12887537147730330940" + "templateHash": "12420339026638684809" }, "name": "Storage Account blob Services", "description": "This module deploys a Storage Account Blob Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." } }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -262,7 +264,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -407,7 +413,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "7740343838101895320" + "templateHash": "2340678191837281561" }, "name": "Storage Account Blob Containers", "description": "This module deploys a Storage Account Blob Container.", @@ -415,77 +421,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -578,7 +586,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/storage/storage-account/file-service/README.md b/avm/res/storage/storage-account/file-service/README.md index af032effaa..3321ebe9ed 100644 --- a/avm/res/storage/storage-account/file-service/README.md +++ b/avm/res/storage/storage-account/file-service/README.md @@ -7,6 +7,7 @@ This module deploys a Storage Account File Share Service. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -57,8 +58,8 @@ The diagnostic settings of the service. | [`logAnalyticsDestinationType`](#parameter-diagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | -| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -135,7 +136,7 @@ The full ARM resource ID of the Marketplace resource to which you would like to ### Parameter: `diagnosticSettings.metricCategories` -The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. +The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. - Required: No - Type: array @@ -168,7 +169,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -231,3 +232,11 @@ File shares to create. | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/storage/storage-account/file-service/main.bicep b/avm/res/storage/storage-account/file-service/main.bicep index 63954599a6..0fcd8ad218 100644 --- a/avm/res/storage/storage-account/file-service/main.bicep +++ b/avm/res/storage/storage-account/file-service/main.bicep @@ -18,8 +18,9 @@ param shareDeleteRetentionPolicy object = { days: 7 } +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? @description('Optional. File shares to create.') param shares array? @@ -92,50 +93,3 @@ output resourceId string = fileServices.id @description('The resource group of the deployed file share service.') output resourceGroupName string = resourceGroup().name -// =============== // -// Definitions // -// =============== // - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? diff --git a/avm/res/storage/storage-account/file-service/main.json b/avm/res/storage/storage-account/file-service/main.json index 3e4af3b534..fcf7489137 100644 --- a/avm/res/storage/storage-account/file-service/main.json +++ b/avm/res/storage/storage-account/file-service/main.json @@ -6,132 +6,134 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "3657184950062156101" + "templateHash": "11334292387756483860" }, "name": "Storage Account File Share Services", "description": "This module deploys a Storage Account File Share Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." } }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -167,7 +169,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -287,7 +293,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "5694394509785243538" + "templateHash": "6729752654389555660" }, "name": "Storage Account File Shares", "description": "This module deploys a Storage Account File Share.", @@ -295,77 +301,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -433,7 +441,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/storage/storage-account/file-service/share/README.md b/avm/res/storage/storage-account/file-service/share/README.md index 7cebc24570..ea95552ebd 100644 --- a/avm/res/storage/storage-account/file-service/share/README.md +++ b/avm/res/storage/storage-account/file-service/share/README.md @@ -7,6 +7,7 @@ This module deploys a Storage Account File Share. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -221,3 +222,11 @@ The maximum size of the share, in gigabytes. Must be greater than 0, and less th | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/storage/storage-account/file-service/share/main.bicep b/avm/res/storage/storage-account/file-service/share/main.bicep index b626c5c212..cfcdfcd9c8 100644 --- a/avm/res/storage/storage-account/file-service/share/main.bicep +++ b/avm/res/storage/storage-account/file-service/share/main.bicep @@ -39,8 +39,9 @@ param enabledProtocols string = 'SMB' @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' +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? resource storageAccount 'Microsoft.Storage/storageAccounts@2023-04-01' existing = { name: storageAccountName @@ -78,33 +79,3 @@ output resourceId string = fileShare.id @description('The resource group of the deployed file share.') output resourceGroupName string = resourceGroup().name - -// =============== // -// Definitions // -// =============== // - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/storage/storage-account/file-service/share/main.json b/avm/res/storage/storage-account/file-service/share/main.json index 6f8f81b2dc..9e09ac6d64 100644 --- a/avm/res/storage/storage-account/file-service/share/main.json +++ b/avm/res/storage/storage-account/file-service/share/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "5694394509785243538" + "templateHash": "6729752654389555660" }, "name": "Storage Account File Shares", "description": "This module deploys a Storage Account File Share.", @@ -14,77 +14,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -152,7 +154,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/storage/storage-account/local-user/main.bicep b/avm/res/storage/storage-account/local-user/main.bicep index 605e5c2f99..95dab99998 100644 --- a/avm/res/storage/storage-account/local-user/main.bicep +++ b/avm/res/storage/storage-account/local-user/main.bicep @@ -25,7 +25,7 @@ param homeDirectory string = '' param permissionScopes array @description('Optional. The local user SSH authorized keys for SFTP.') -param sshAuthorizedKeys sshAuthorizedKeysType +param sshAuthorizedKeys sshAuthorizedKeysType? resource storageAccount 'Microsoft.Storage/storageAccounts@2023-04-01' existing = { name: storageAccountName @@ -67,4 +67,4 @@ type sshAuthorizedKeysType = { @description('Required. SSH public key base64 encoded. The format should be: \'{keyType} {keyData}\', e.g. ssh-rsa AAAABBBB.') key: string }[] -}? +} diff --git a/avm/res/storage/storage-account/local-user/main.json b/avm/res/storage/storage-account/local-user/main.json index 8a19e11da9..d607b2b771 100644 --- a/avm/res/storage/storage-account/local-user/main.json +++ b/avm/res/storage/storage-account/local-user/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "14184905621772237225" + "templateHash": "4771770611168248415" }, "name": "Storage Account Local Users", "description": "This module deploys a Storage Account Local User, which is used for SFTP authentication.", @@ -40,8 +40,7 @@ "description": "Optional. The list of SSH authorized keys." } } - }, - "nullable": true + } } }, "parameters": { @@ -92,6 +91,7 @@ }, "sshAuthorizedKeys": { "$ref": "#/definitions/sshAuthorizedKeysType", + "nullable": true, "metadata": { "description": "Optional. The local user SSH authorized keys for SFTP." } diff --git a/avm/res/storage/storage-account/main.bicep b/avm/res/storage/storage-account/main.bicep index 8e491ac177..9dfc1ca705 100644 --- a/avm/res/storage/storage-account/main.bicep +++ b/avm/res/storage/storage-account/main.bicep @@ -9,11 +9,13 @@ param name string @description('Optional. Location for all resources.') param location string = resourceGroup().location +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityAllType? @allowed([ 'Storage' @@ -62,8 +64,9 @@ param defaultToOAuthAuthentication bool = false @description('Optional. Indicates whether the storage account permits requests to be authorized with the account access key via Shared Key. If false, then all requests, including shared access signatures, must be authorized with Azure Active Directory (Azure AD). The default value is null, which is equivalent to true.') param allowSharedKeyAccess bool = true +import { privateEndpointMultiServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointMultiServiceType[]? @description('Optional. The Storage Account ManagementPolicies Rules.') param managementPolicyRules array? @@ -135,11 +138,13 @@ param isLocalUserEnabled bool = false @description('Optional. If true, enables NFS 3.0 support for the storage account. Requires enableHierarchicalNamespace to be true.') param enableNfsV3 bool = false +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? @description('Optional. Tags of the resource.') param tags object? @@ -166,8 +171,9 @@ param publicNetworkAccess string = '' @description('Optional. Allows HTTPS traffic only to storage service if sets to true.') param supportsHttpsTrafficOnly bool = true +import { customerManagedKeyType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The customer managed key definition.') -param customerManagedKey customerManagedKeyType +param customerManagedKey customerManagedKeyType? @description('Optional. The SAS expiration period. DD.HH:MM:SS.') param sasExpirationPeriod string = '' @@ -709,6 +715,7 @@ output privateEndpoints array = [ } ] +import { secretsOutputType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.') output exportedSecrets secretsOutputType = (secretsExportConfiguration != null) ? toObject(secretsExport.outputs.secretsSet, secret => last(split(secret.secretResourceId, '/')), secret => secret) @@ -718,48 +725,7 @@ output exportedSecrets secretsOutputType = (secretsExportConfiguration != null) // Definitions // // =============== // -type managedIdentitiesType = { - @description('Optional. Enables system assigned managed identity on the resource.') - systemAssigned: bool? - - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[]? -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - +@export() type networkAclsType = { @description('Optional. Sets the resource access rules. Array entries must consist of "tenantId" and "resourceId" fields only.') resourceAccessRules: { @@ -791,139 +757,7 @@ type networkAclsType = { defaultAction: ('Allow' | 'Deny')? } -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Required. The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file".') - service: string - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? - - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? - - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint ip address.') - fqdn: string? - - @description('Required. A list of private ip addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private ip address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? - -type customerManagedKeyType = { - @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') - keyVaultResourceId: string - - @description('Required. The name of the customer managed key to use for encryption.') - keyName: string - - @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') - keyVersion: string? - - @description('Optional. User assigned identity to use when fetching the customer managed key. If used must also be specified in `managedIdentities.userAssignedResourceIds`. Required if no system assigned identity is available for use.') - userAssignedIdentityResourceId: string? -}? - +@export() type secretsExportConfigurationType = { @description('Required. The key vault name where to store the keys and connection strings generated by the modules.') keyVaultResourceId: string @@ -940,9 +774,3 @@ type secretsExportConfigurationType = { @description('Optional. The connectionString2 secret name to create.') connectionString2: string? } - -import { secretSetType } from 'modules/keyVaultExport.bicep' -type secretsOutputType = { - @description('An exported secret\'s references.') - *: secretSetType -} diff --git a/avm/res/storage/storage-account/main.json b/avm/res/storage/storage-account/main.json index b6d1cc5d74..0b9ea0bd04 100644 --- a/avm/res/storage/storage-account/main.json +++ b/avm/res/storage/storage-account/main.json @@ -6,134 +6,13 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "7109049210516898074" + "templateHash": "4420850353095628584" }, "name": "Storage Accounts", "description": "This module deploys a Storage Account.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { - "type": "object", - "properties": { - "systemAssigned": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." - } - }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." - } - } - }, - "nullable": true - }, - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, "networkAclsType": { "type": "object", "properties": { @@ -203,414 +82,637 @@ "description": "Optional. Specifies the default action of allow or deny when no other rules match." } } + }, + "metadata": { + "__bicep_export!": true } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "metadata": { - "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." - } + "secretsExportConfigurationType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The key vault name where to store the keys and connection strings generated by the modules." + } + }, + "accessKey1": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The accessKey1 secret name to create." + } + }, + "connectionString1": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The connectionString1 secret name to create." + } + }, + "accessKey2": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The accessKey2 secret name to create." + } + }, + "connectionString2": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The connectionString2 secret name to create." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "_1.privateEndpointCustomDnsConfigType": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "privateDnsZoneGroup": { + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." + "description": "Optional. The name of the private DNS Zone Group config." } }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, + "privateDnsZoneResourceId": { + "type": "string", "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } + "description": "Required. The resource id of the private DNS zone." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." } }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } - }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "_1.secretSetOutputType": { + "type": "object", + "properties": { + "secretResourceId": { + "type": "string", + "metadata": { + "description": "The resourceId of the exported secret." + } + }, + "secretUri": { + "type": "string", + "metadata": { + "description": "The secret URI of the exported secret." + } + }, + "secretUriWithVersion": { + "type": "string", + "metadata": { + "description": "The secret URI with version of the exported secret." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for the output of the secret set via the secrets export feature.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a customer-managed key.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } } }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "privateEndpointMultiServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "metadata": { + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\" for a Storage Account's Private Endpoints." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." } - } - }, - "nullable": true - }, - "customerManagedKeyType": { - "type": "object", - "properties": { - "keyVaultResourceId": { + }, + "customNetworkInterfaceName": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + "description": "Optional. The custom name of the network interface attached to the private endpoint." } }, - "keyName": { - "type": "string", + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { - "description": "Required. The name of the customer managed key to use for encryption." + "description": "Optional. Specify the type of lock." } }, - "keyVersion": { - "type": "string", + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, "nullable": true, "metadata": { - "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + "description": "Optional. Array of role assignments to create." } }, - "userAssignedIdentityResourceId": { + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. User assigned identity to use when fetching the customer managed key. If used must also be specified in `managedIdentities.userAssignedResourceIds`. Required if no system assigned identity is available for use." + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can NOT be assumed (i.e., for services that have more than one subresource, like Storage Account with Blob (blob, table, queue, file, ...).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "secretsExportConfigurationType": { + "roleAssignmentType": { "type": "object", "properties": { - "keyVaultResourceId": { + "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The key vault name where to store the keys and connection strings generated by the modules." + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "accessKey1": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], "nullable": true, "metadata": { - "description": "Optional. The accessKey1 secret name to create." + "description": "Optional. The principal type of the assigned principal ID." } }, - "connectionString1": { + "description": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The connectionString1 secret name to create." + "description": "Optional. The description of the role assignment." } }, - "accessKey2": { + "condition": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The accessKey2 secret name to create." + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." } }, - "connectionString2": { + "conditionVersion": { "type": "string", + "allowedValues": [ + "2.0" + ], "nullable": true, "metadata": { - "description": "Optional. The connectionString2 secret name to create." + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } } }, "secretsOutputType": { "type": "object", "properties": {}, "additionalProperties": { - "$ref": "#/definitions/secretSetType", + "$ref": "#/definitions/_1.secretSetOutputType", "metadata": { "description": "An exported secret's references." } - } - }, - "secretSetType": { - "type": "object", - "properties": { - "secretResourceId": { - "type": "string", - "metadata": { - "description": "The resourceId of the exported secret." - } - }, - "secretUri": { - "type": "string", - "metadata": { - "description": "The secret URI of the exported secret." - } - } }, "metadata": { + "description": "A map of the exported secrets", "__bicep_imported_from!": { - "sourceTemplate": "modules/keyVaultExport.bicep" + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" } } } @@ -631,13 +733,18 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } @@ -718,7 +825,11 @@ } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointMultiServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } @@ -859,13 +970,18 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } @@ -917,6 +1033,7 @@ }, "customerManagedKey": { "$ref": "#/definitions/customerManagedKeyType", + "nullable": true, "metadata": { "description": "Optional. The customer managed key definition." } @@ -2047,7 +2164,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "14184905621772237225" + "templateHash": "4771770611168248415" }, "name": "Storage Account Local Users", "description": "This module deploys a Storage Account Local User, which is used for SFTP authentication.", @@ -2081,8 +2198,7 @@ "description": "Optional. The list of SSH authorized keys." } } - }, - "nullable": true + } } }, "parameters": { @@ -2133,6 +2249,7 @@ }, "sshAuthorizedKeys": { "$ref": "#/definitions/sshAuthorizedKeysType", + "nullable": true, "metadata": { "description": "Optional. The local user SSH authorized keys for SFTP." } @@ -2265,132 +2382,134 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "12887537147730330940" + "templateHash": "12420339026638684809" }, "name": "Storage Account blob Services", "description": "This module deploys a Storage Account Blob Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." } }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -2521,7 +2640,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -2666,7 +2789,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "7740343838101895320" + "templateHash": "2340678191837281561" }, "name": "Storage Account Blob Containers", "description": "This module deploys a Storage Account Blob Container.", @@ -2674,77 +2797,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -2837,7 +2962,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -3136,132 +3265,134 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "3657184950062156101" + "templateHash": "11334292387756483860" }, "name": "Storage Account File Share Services", "description": "This module deploys a Storage Account File Share Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." } }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -3297,7 +3428,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -3416,86 +3551,88 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "5694394509785243538" - }, - "name": "Storage Account File Shares", - "description": "This module deploys a Storage Account File Share.", - "owner": "Azure/module-maintainers" - }, - "definitions": { - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "version": "0.30.23.60470", + "templateHash": "6729752654389555660" + }, + "name": "Storage Account File Shares", + "description": "This module deploys a Storage Account File Share.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -3563,7 +3700,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -3900,132 +4041,134 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "6947504466788447852" + "templateHash": "8427226755569651235" }, "name": "Storage Account Queue Services", "description": "This module deploys a Storage Account Queue Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." } }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -4044,7 +4187,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -4145,7 +4292,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "6090221832347220924" + "templateHash": "17434851913053254324" }, "name": "Storage Account Queues", "description": "This module deploys a Storage Account Queue.", @@ -4153,77 +4300,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -4244,11 +4393,15 @@ "type": "object", "defaultValue": {}, "metadata": { - "description": "Required. A name-value pair that represents queue metadata." + "description": "Optional. A name-value pair that represents queue metadata." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -4416,132 +4569,134 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "6657632516379685259" + "templateHash": "8854918982965924242" }, "name": "Storage Account Table Services", "description": "This module deploys a Storage Account Table Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." } }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -4560,7 +4715,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -4658,7 +4817,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "7397003163362434404" + "templateHash": "14487041808457984428" }, "name": "Storage Account Table", "description": "This module deploys a Storage Account Table.", @@ -4666,77 +4825,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -4748,7 +4909,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -4916,11 +5081,11 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "12263717469683062316" + "templateHash": "13337765828606873307" } }, "definitions": { - "secretSetType": { + "secretSetOutputType": { "type": "object", "properties": { "secretResourceId": { @@ -4934,10 +5099,19 @@ "metadata": { "description": "The secret URI of the exported secret." } + }, + "secretUriWithVersion": { + "type": "string", + "metadata": { + "description": "The secret URI with version of the exported secret." + } } }, "metadata": { - "__bicep_export!": true + "description": "An AVM-aligned type for the output of the secret set via the secrets export feature.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } } }, "secretToSetType": { @@ -4955,6 +5129,12 @@ "description": "Required. The value of the secret to set." } } + }, + "metadata": { + "description": "An AVM-aligned type for the secret to set via the secrets export feature.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } } } }, @@ -5002,7 +5182,7 @@ "secretsSet": { "type": "array", "items": { - "$ref": "#/definitions/secretSetType" + "$ref": "#/definitions/secretSetOutputType" }, "metadata": { "description": "The references to the secrets exported to the provided Key Vault." @@ -5011,7 +5191,8 @@ "count": "[length(range(0, length(coalesce(parameters('secretsToSet'), createArray()))))]", "input": { "secretResourceId": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('secretsToSet')[range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()]].name)]", - "secretUri": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUri]" + "secretUri": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUri]", + "secretUriWithVersion": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUriWithVersion]" } } } @@ -5097,4 +5278,4 @@ "value": "[if(not(equals(parameters('secretsExportConfiguration'), null())), toObject(reference('secretsExport').outputs.secretsSet.value, lambda('secret', last(split(lambdaVariables('secret').secretResourceId, '/'))), lambda('secret', lambdaVariables('secret'))), createObject())]" } } -} +} \ No newline at end of file diff --git a/avm/res/storage/storage-account/modules/keyVaultExport.bicep b/avm/res/storage/storage-account/modules/keyVaultExport.bicep index d537d2407e..66db71c112 100644 --- a/avm/res/storage/storage-account/modules/keyVaultExport.bicep +++ b/avm/res/storage/storage-account/modules/keyVaultExport.bicep @@ -5,6 +5,7 @@ @description('Required. The name of the Key Vault to set the ecrets in.') param keyVaultName string +import { secretToSetType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Required. The secrets to set in the Key Vault.') param secretsToSet secretToSetType[] @@ -29,34 +30,13 @@ resource secrets 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = [ // =========== // // Outputs // // =========== // - +import { secretSetOutputType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('The references to the secrets exported to the provided Key Vault.') -output secretsSet secretSetType[] = [ +output secretsSet secretSetOutputType[] = [ #disable-next-line outputs-should-not-contain-secrets // Only returning the references, not a secret value for index in range(0, length(secretsToSet ?? [])): { secretResourceId: secrets[index].id secretUri: secrets[index].properties.secretUri + secretUriWithVersion: secrets[index].properties.secretUriWithVersion } ] - -// =============== // -// Definitions // -// =============== // - -@export() -type secretSetType = { - @description('The resourceId of the exported secret.') - secretResourceId: string - - @description('The secret URI of the exported secret.') - secretUri: string -} - -type secretToSetType = { - @description('Required. The name of the secret to set.') - name: string - - @description('Required. The value of the secret to set.') - @secure() - value: string -} diff --git a/avm/res/storage/storage-account/queue-service/README.md b/avm/res/storage/storage-account/queue-service/README.md index 94ce2dacff..5c8d2c0fbb 100644 --- a/avm/res/storage/storage-account/queue-service/README.md +++ b/avm/res/storage/storage-account/queue-service/README.md @@ -7,6 +7,7 @@ This module deploys a Storage Account Queue Service. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -55,8 +56,8 @@ The diagnostic settings of the service. | [`logAnalyticsDestinationType`](#parameter-diagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | -| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -133,7 +134,7 @@ The full ARM resource ID of the Marketplace resource to which you would like to ### Parameter: `diagnosticSettings.metricCategories` -The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. +The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. - Required: No - Type: array @@ -166,7 +167,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -199,3 +200,11 @@ Queues to create. | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/storage/storage-account/queue-service/main.bicep b/avm/res/storage/storage-account/queue-service/main.bicep index 8bb3d4f8f2..d50c991cb2 100644 --- a/avm/res/storage/storage-account/queue-service/main.bicep +++ b/avm/res/storage/storage-account/queue-service/main.bicep @@ -9,8 +9,9 @@ param storageAccountName string @description('Optional. Queues to create.') param queues array? +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? // The name of the blob services var name = 'default' @@ -74,51 +75,3 @@ output resourceId string = queueServices.id @description('The resource group of the deployed file share service.') output resourceGroupName string = resourceGroup().name - -// =============== // -// Definitions // -// =============== // - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? diff --git a/avm/res/storage/storage-account/queue-service/main.json b/avm/res/storage/storage-account/queue-service/main.json index 6fc76d0b47..557dc74aa0 100644 --- a/avm/res/storage/storage-account/queue-service/main.json +++ b/avm/res/storage/storage-account/queue-service/main.json @@ -6,132 +6,134 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "6947504466788447852" + "templateHash": "8427226755569651235" }, "name": "Storage Account Queue Services", "description": "This module deploys a Storage Account Queue Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." } }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -150,7 +152,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -251,7 +257,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "6090221832347220924" + "templateHash": "17434851913053254324" }, "name": "Storage Account Queues", "description": "This module deploys a Storage Account Queue.", @@ -259,77 +265,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -350,11 +358,15 @@ "type": "object", "defaultValue": {}, "metadata": { - "description": "Required. A name-value pair that represents queue metadata." + "description": "Optional. A name-value pair that represents queue metadata." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/storage/storage-account/queue-service/queue/README.md b/avm/res/storage/storage-account/queue-service/queue/README.md index 140ca97388..da14c3e7ef 100644 --- a/avm/res/storage/storage-account/queue-service/queue/README.md +++ b/avm/res/storage/storage-account/queue-service/queue/README.md @@ -7,6 +7,7 @@ This module deploys a Storage Account Queue. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -21,7 +22,6 @@ This module deploys a Storage Account Queue. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`metadata`](#parameter-metadata) | object | A name-value pair that represents queue metadata. | | [`name`](#parameter-name) | string | The name of the storage queue to deploy. | **Conditional parameters** @@ -34,16 +34,9 @@ This module deploys a Storage Account Queue. | Parameter | Type | Description | | :-- | :-- | :-- | +| [`metadata`](#parameter-metadata) | object | A name-value pair that represents queue metadata. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | -### Parameter: `metadata` - -A name-value pair that represents queue metadata. - -- Required: No -- Type: object -- Default: `{}` - ### Parameter: `name` The name of the storage queue to deploy. @@ -58,6 +51,14 @@ The name of the parent Storage Account. Required if the template is used in a st - Required: Yes - Type: string +### Parameter: `metadata` + +A name-value pair that represents queue metadata. + +- Required: No +- Type: object +- Default: `{}` + ### Parameter: `roleAssignments` Array of role assignments to create. @@ -176,3 +177,11 @@ The principal type of the assigned principal ID. | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/storage/storage-account/queue-service/queue/main.bicep b/avm/res/storage/storage-account/queue-service/queue/main.bicep index 4b0f656ef0..9c83db4d2f 100644 --- a/avm/res/storage/storage-account/queue-service/queue/main.bicep +++ b/avm/res/storage/storage-account/queue-service/queue/main.bicep @@ -9,11 +9,12 @@ param storageAccountName string @description('Required. The name of the storage queue to deploy.') param name string -@description('Required. A name-value pair that represents queue metadata.') +@description('Optional. A name-value pair that represents queue metadata.') param metadata object = {} +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -112,33 +113,3 @@ output resourceId string = queue.id @description('The resource group of the deployed queue.') output resourceGroupName string = resourceGroup().name - -// =============== // -// Definitions // -// =============== // - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/storage/storage-account/queue-service/queue/main.json b/avm/res/storage/storage-account/queue-service/queue/main.json index 2aad9fefb2..a3f4c271ec 100644 --- a/avm/res/storage/storage-account/queue-service/queue/main.json +++ b/avm/res/storage/storage-account/queue-service/queue/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "6090221832347220924" + "templateHash": "17434851913053254324" }, "name": "Storage Account Queues", "description": "This module deploys a Storage Account Queue.", @@ -14,77 +14,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -105,11 +107,15 @@ "type": "object", "defaultValue": {}, "metadata": { - "description": "Required. A name-value pair that represents queue metadata." + "description": "Optional. A name-value pair that represents queue metadata." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/storage/storage-account/table-service/README.md b/avm/res/storage/storage-account/table-service/README.md index 7f65d890d0..ba3f15b61d 100644 --- a/avm/res/storage/storage-account/table-service/README.md +++ b/avm/res/storage/storage-account/table-service/README.md @@ -7,6 +7,7 @@ This module deploys a Storage Account Table Service. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -55,8 +56,8 @@ The diagnostic settings of the service. | [`logAnalyticsDestinationType`](#parameter-diagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | | [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | -| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | -| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of the diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | | [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | 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. | @@ -133,7 +134,7 @@ The full ARM resource ID of the Marketplace resource to which you would like to ### Parameter: `diagnosticSettings.metricCategories` -The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. +The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection. - Required: No - Type: array @@ -166,7 +167,7 @@ Enable or disable the category explicitly. Default is `true`. ### Parameter: `diagnosticSettings.name` -The name of diagnostic setting. +The name of the diagnostic setting. - Required: No - Type: string @@ -200,3 +201,11 @@ tables to create. | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/storage/storage-account/table-service/main.bicep b/avm/res/storage/storage-account/table-service/main.bicep index 061dbb9ca0..8f7c9ab9a1 100644 --- a/avm/res/storage/storage-account/table-service/main.bicep +++ b/avm/res/storage/storage-account/table-service/main.bicep @@ -9,8 +9,9 @@ param storageAccountName string @description('Optional. tables to create.') param tables array = [] +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingFullType[]? // The name of the table service var name = 'default' @@ -73,51 +74,3 @@ output resourceId string = tableServices.id @description('The resource group of the deployed table service.') output resourceGroupName string = resourceGroup().name - -// =============== // -// Definitions // -// =============== // - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') - categoryGroup: string? - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') - category: string - - @description('Optional. Enable or disable the category explicitly. Default is `true`.') - enabled: bool? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? diff --git a/avm/res/storage/storage-account/table-service/main.json b/avm/res/storage/storage-account/table-service/main.json index df8cac0dbd..1e7afc9986 100644 --- a/avm/res/storage/storage-account/table-service/main.json +++ b/avm/res/storage/storage-account/table-service/main.json @@ -6,132 +6,134 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "6657632516379685259" + "templateHash": "8854918982965924242" }, "name": "Storage Account Table Services", "description": "This module deploys a Storage Account Table Service.", "owner": "Azure/module-maintainers" }, "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." } }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -150,7 +152,11 @@ } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -248,7 +254,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "7397003163362434404" + "templateHash": "14487041808457984428" }, "name": "Storage Account Table", "description": "This module deploys a Storage Account Table.", @@ -256,77 +262,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -338,7 +346,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/storage/storage-account/table-service/table/README.md b/avm/res/storage/storage-account/table-service/table/README.md index 63e5d835bf..8fda131b17 100644 --- a/avm/res/storage/storage-account/table-service/table/README.md +++ b/avm/res/storage/storage-account/table-service/table/README.md @@ -7,6 +7,7 @@ This module deploys a Storage Account Table. - [Resource Types](#Resource-Types) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) ## Resource Types @@ -165,3 +166,11 @@ The principal type of the assigned principal ID. | `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. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | diff --git a/avm/res/storage/storage-account/table-service/table/main.bicep b/avm/res/storage/storage-account/table-service/table/main.bicep index 9b76e2f338..d5cb0b65a1 100644 --- a/avm/res/storage/storage-account/table-service/table/main.bicep +++ b/avm/res/storage/storage-account/table-service/table/main.bicep @@ -6,8 +6,9 @@ metadata owner = 'Azure/module-maintainers' @description('Conditional. The name of the parent Storage Account. Required if the template is used in a standalone deployment.') param storageAccountName string +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Required. Name of the table.') param name string @@ -98,33 +99,3 @@ output resourceId string = table.id @description('The resource group of the deployed file share service.') output resourceGroupName string = resourceGroup().name - -// =============== // -// Definitions // -// =============== // - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/storage/storage-account/table-service/table/main.json b/avm/res/storage/storage-account/table-service/table/main.json index 15dc63d03b..7b2fe4c3e4 100644 --- a/avm/res/storage/storage-account/table-service/table/main.json +++ b/avm/res/storage/storage-account/table-service/table/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "7397003163362434404" + "templateHash": "14487041808457984428" }, "name": "Storage Account Table", "description": "This module deploys a Storage Account Table.", @@ -14,77 +14,79 @@ }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -96,7 +98,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } diff --git a/avm/res/storage/storage-account/tests/e2e/max/main.test.bicep b/avm/res/storage/storage-account/tests/e2e/max/main.test.bicep index 87651382b4..8d781c4b09 100644 --- a/avm/res/storage/storage-account/tests/e2e/max/main.test.bicep +++ b/avm/res/storage/storage-account/tests/e2e/max/main.test.bicep @@ -250,8 +250,6 @@ module testDeployment '../../../main.bicep' = [ metadata: { testKey: 'testValue' } - enableWORM: true - WORMRetention: 666 allowProtectedAppendWrites: false } ] diff --git a/avm/res/storage/storage-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/storage/storage-account/tests/e2e/waf-aligned/main.test.bicep index 2764fa29fc..7792611a5f 100644 --- a/avm/res/storage/storage-account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/storage/storage-account/tests/e2e/waf-aligned/main.test.bicep @@ -154,8 +154,6 @@ module testDeployment '../../../main.bicep' = [ metadata: { testKey: 'testValue' } - enableWORM: true - WORMRetention: 666 allowProtectedAppendWrites: false } ] diff --git a/avm/res/synapse/private-link-hub/README.md b/avm/res/synapse/private-link-hub/README.md index d0dba94113..8121cd395a 100644 --- a/avm/res/synapse/private-link-hub/README.md +++ b/avm/res/synapse/private-link-hub/README.md @@ -556,22 +556,22 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the Private Endpoint IP configuration is included. | | [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | -| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the Private Endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. | | [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | -| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the Private Endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | -| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS zone group to configure for the private endpoint. | +| [`name`](#parameter-privateendpointsname) | string | The name of the Private Endpoint. | +| [`privateDnsZoneGroup`](#parameter-privateendpointsprivatednszonegroup) | object | The private DNS Zone Group to configure for the Private Endpoint. | | [`privateLinkServiceConnectionName`](#parameter-privateendpointsprivatelinkserviceconnectionname) | string | The name of the private link connection to create. | -| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. | +| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | -| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/Resource Groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -582,7 +582,7 @@ Resource ID of the subnet where the endpoint needs to be created. ### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` -Application security groups in which the private endpoint IP configuration is included. +Application security groups in which the Private Endpoint IP configuration is included. - Required: No - Type: array @@ -598,15 +598,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -615,9 +613,16 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` -The custom name of the network interface attached to the private endpoint. +The custom name of the network interface attached to the Private Endpoint. - Required: No - Type: string @@ -631,7 +636,7 @@ Enable/Disable usage telemetry for module. ### Parameter: `privateEndpoints.ipConfigurations` -A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. +A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints. - Required: No - Type: array @@ -695,7 +700,7 @@ If Manual Private Link Connection is required. ### Parameter: `privateEndpoints.location` -The location to deploy the private endpoint to. +The location to deploy the Private Endpoint to. - Required: No - Type: string @@ -745,14 +750,14 @@ A message passed to the owner of the remote resource with the manual connection ### Parameter: `privateEndpoints.name` -The name of the private endpoint. +The name of the Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.privateDnsZoneGroup` -The private DNS zone group to configure for the private endpoint. +The private DNS Zone Group to configure for the Private Endpoint. - Required: No - Type: object @@ -761,7 +766,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -771,7 +776,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -786,7 +791,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -797,7 +802,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -818,7 +823,7 @@ The name of the private link connection to create. ### Parameter: `privateEndpoints.resourceGroupName` -Specify if you want to deploy the Private Endpoint into a different resource group than the main resource. +Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource. - Required: No - Type: string @@ -933,14 +938,14 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". +The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint. - Required: No - Type: string ### Parameter: `privateEndpoints.tags` -Tags to be applied on all resources/resource groups in this deployment. +Tags to be applied on all resources/Resource Groups in this deployment. - Required: No - Type: object @@ -1072,6 +1077,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/synapse/private-link-hub/main.bicep b/avm/res/synapse/private-link-hub/main.bicep index 60406e8ea0..578825e611 100644 --- a/avm/res/synapse/private-link-hub/main.bicep +++ b/avm/res/synapse/private-link-hub/main.bicep @@ -11,17 +11,20 @@ param location string = resourceGroup().location @description('Optional. Tags of the resource.') param tags object? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointSingleServiceType[]? var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -177,128 +180,3 @@ output privateEndpoints array = [ networkInterfaceIds: privateLinkHub_privateEndpoints[i].outputs.networkInterfaceIds } ] - -// =============== // -// Definitions // -// =============== // - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') - service: string? - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? - - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? - - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? - - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? diff --git a/avm/res/synapse/private-link-hub/main.json b/avm/res/synapse/private-link-hub/main.json index bdf5c2772a..bdf7440ec8 100644 --- a/avm/res/synapse/private-link-hub/main.json +++ b/avm/res/synapse/private-link-hub/main.json @@ -5,331 +5,369 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6865603283108816559" + "version": "0.30.23.60470", + "templateHash": "4249101597778316184" }, "name": "Azure Synapse Analytics", "description": "This module deploys an Azure Synapse Analytics (Private Link Hub).", "owner": "Azure/module-maintainers" }, "definitions": { - "lockType": { + "_1.privateEndpointCustomDnsConfigType": { "type": "object", "properties": { - "name": { + "fqdn": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Required. A list of private IP addresses of the private endpoint." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." - } - }, - "privateDnsZoneGroup": { + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." + "description": "Optional. The name of the private DNS Zone Group config." } }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, + "privateDnsZoneResourceId": { + "type": "string", "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + "description": "Required. The resource id of the private DNS zone." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." } }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "privateEndpointSingleServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private Endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the Private Endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the Private Endpoint for. For example \"vault\" for a Key Vault Private Endpoint." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS Zone Group to configure for the Private Endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the Private Endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the Private Endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/Resource Groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like 'vault' for key vault).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -355,6 +393,7 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } @@ -367,13 +406,21 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointSingleServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } diff --git a/avm/res/synapse/workspace/README.md b/avm/res/synapse/workspace/README.md index 5e52048a3a..0bc85c9350 100644 --- a/avm/res/synapse/workspace/README.md +++ b/avm/res/synapse/workspace/README.md @@ -1422,7 +1422,7 @@ The diagnostic settings of the service. | [`eventHubAuthorizationRuleResourceId`](#parameter-diagnosticsettingseventhubauthorizationruleresourceid) | 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. | | [`eventHubName`](#parameter-diagnosticsettingseventhubname) | 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. | | [`logAnalyticsDestinationType`](#parameter-diagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | -| [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. | | [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | | [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | | [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | 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. | @@ -1458,7 +1458,7 @@ A string indicating whether the export to Log Analytics should use the default d ### Parameter: `diagnosticSettings.logCategoriesAndGroups` -The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. +The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection. - Required: No - Type: array @@ -1468,7 +1468,8 @@ The name of logs that will be streamed. "allLogs" includes all possible logs for | Parameter | Type | Description | | :-- | :-- | :-- | | [`category`](#parameter-diagnosticsettingslogcategoriesandgroupscategory) | string | Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here. | -| [`categoryGroup`](#parameter-diagnosticsettingslogcategoriesandgroupscategorygroup) | string | Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs. | +| [`categoryGroup`](#parameter-diagnosticsettingslogcategoriesandgroupscategorygroup) | string | Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs. | +| [`enabled`](#parameter-diagnosticsettingslogcategoriesandgroupsenabled) | bool | Enable or disable the category explicitly. Default is `true`. | ### Parameter: `diagnosticSettings.logCategoriesAndGroups.category` @@ -1479,11 +1480,18 @@ Name of a Diagnostic Log category for a resource type this setting is applied to ### Parameter: `diagnosticSettings.logCategoriesAndGroups.categoryGroup` -Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs. +Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs. - Required: No - Type: string +### Parameter: `diagnosticSettings.logCategoriesAndGroups.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + ### Parameter: `diagnosticSettings.marketplacePartnerResourceId` The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. @@ -1643,13 +1651,13 @@ The managed identity definition for this resource. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | ### Parameter: `managedIdentities.userAssignedResourceIds` -The resource ID(s) to assign to the resource. +The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. -- Required: Yes +- Required: No - Type: array ### Parameter: `managedResourceGroupName` @@ -1687,7 +1695,7 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file" for a Storage Account's Private Endpoints. | | [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | **Optional parameters** @@ -1712,7 +1720,7 @@ Configuration details for private endpoints. For security reasons, it is recomme ### Parameter: `privateEndpoints.service` -The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". +The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file" for a Storage Account's Private Endpoints. - Required: Yes - Type: string @@ -1742,15 +1750,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -1759,6 +1765,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -1905,7 +1918,7 @@ The private DNS zone group to configure for the private endpoint. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. | +| [`privateDnsZoneGroupConfigs`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigs) | array | The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. | **Optional parameters** @@ -1915,7 +1928,7 @@ The private DNS zone group to configure for the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs` -The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones. +The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones. - Required: Yes - Type: array @@ -1930,7 +1943,7 @@ The private DNS zone groups to associate the private endpoint. A DNS zone group | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS zone group config. | +| [`name`](#parameter-privateendpointsprivatednszonegroupprivatednszonegroupconfigsname) | string | The name of the private DNS Zone Group config. | ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.privateDnsZoneResourceId` @@ -1941,7 +1954,7 @@ The resource id of the private DNS zone. ### Parameter: `privateEndpoints.privateDnsZoneGroup.privateDnsZoneGroupConfigs.name` -The name of the private DNS zone group config. +The name of the private DNS Zone Group config. - Required: No - Type: string @@ -2250,6 +2263,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | ## Data Collection diff --git a/avm/res/synapse/workspace/administrators/main.json b/avm/res/synapse/workspace/administrators/main.json index bb9e0505cd..09e136c25e 100644 --- a/avm/res/synapse/workspace/administrators/main.json +++ b/avm/res/synapse/workspace/administrators/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15890618337043813918" + "version": "0.30.23.60470", + "templateHash": "11234358964964275645" }, "name": "Synapse Workspaces Administrators", "description": "This module deploys Synapse Workspaces Administrators.", diff --git a/avm/res/synapse/workspace/firewall-rules/main.json b/avm/res/synapse/workspace/firewall-rules/main.json index ce7fd0baaa..628d2c6d98 100644 --- a/avm/res/synapse/workspace/firewall-rules/main.json +++ b/avm/res/synapse/workspace/firewall-rules/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6729418057172891787" + "version": "0.30.23.60470", + "templateHash": "1410907925603155251" }, "name": "Synapse Workspaces Firewall Rules", "description": "This module deploys Synapse Workspaces Firewall Rules.", diff --git a/avm/res/synapse/workspace/integration-runtime/main.json b/avm/res/synapse/workspace/integration-runtime/main.json index 07711c9fcc..0b1fe277af 100644 --- a/avm/res/synapse/workspace/integration-runtime/main.json +++ b/avm/res/synapse/workspace/integration-runtime/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4134219125418987684" + "version": "0.30.23.60470", + "templateHash": "2875700223215345190" }, "name": "Synapse Workspace Integration Runtimes", "description": "This module deploys a Synapse Workspace Integration Runtime.", diff --git a/avm/res/synapse/workspace/key/main.json b/avm/res/synapse/workspace/key/main.json index d98324c30c..704f8e78b6 100644 --- a/avm/res/synapse/workspace/key/main.json +++ b/avm/res/synapse/workspace/key/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6170014210030770909" + "version": "0.30.23.60470", + "templateHash": "15229329511207297146" }, "name": "Synapse Workspaces Keys", "description": "This module deploys a Synapse Workspaces Key.", diff --git a/avm/res/synapse/workspace/main.bicep b/avm/res/synapse/workspace/main.bicep index e67c879082..0a27c87f95 100644 --- a/avm/res/synapse/workspace/main.bicep +++ b/avm/res/synapse/workspace/main.bicep @@ -32,10 +32,11 @@ param defaultDataLakeStorageFilesystem string param defaultDataLakeStorageCreateManagedPrivateEndpoint bool = false @description('Optional. The Entra ID administrator for the synapse workspace.') -param administrator adminType +param administrator administratorType? +import { customerManagedKeyType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The customer managed key definition.') -param customerManagedKey customerManagedKeyType +param customerManagedKey customerManagedKeyType? @description('Optional. Activate workspace by adding the system managed identity in the KeyVault containing the customer managed key and activating the workspace.') param encryptionActivateWorkspace bool = false @@ -85,20 +86,25 @@ param accountUrl string = 'https://${last(split(defaultDataLakeStorageAccountRes @description('Optional. Git integration settings.') param workspaceRepositoryConfiguration object? +import { managedIdentityOnlyUserAssignedType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityOnlyUserAssignedType? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? +import { privateEndpointMultiServiceType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointType +param privateEndpoints privateEndpointMultiServiceType[]? +import { diagnosticSettingLogsOnlyType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingType +param diagnosticSettings diagnosticSettingLogsOnlyType[]? // Variables @@ -253,7 +259,7 @@ module synapse_integrationRuntimes 'integration-runtime/main.bicep' = [ workspaceName: workspace.name name: integrationRuntime.name type: integrationRuntime.type - typeProperties: contains(integrationRuntime, 'typeProperties') ? integrationRuntime.typeProperties : {} + typeProperties: integrationRuntime.?typeProperties ?? {} } } ] @@ -453,179 +459,9 @@ output privateEndpoints array = [ // Definitions // // =============== // -type managedIdentitiesType = { - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[] -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type privateEndpointType = { - @description('Optional. The name of the private endpoint.') - name: string? - - @description('Optional. The location to deploy the private endpoint to.') - location: string? - - @description('Optional. The name of the private link connection to create.') - privateLinkServiceConnectionName: string? - - @description('Required. The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file".') - service: string - - @description('Required. Resource ID of the subnet where the endpoint needs to be created.') - subnetResourceId: string - - @description('Optional. The private DNS zone group to configure for the private endpoint.') - privateDnsZoneGroup: { - @description('Optional. The name of the Private DNS Zone Group.') - name: string? - - @description('Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones.') - privateDnsZoneGroupConfigs: { - @description('Optional. The name of the private DNS zone group config.') - name: string? - - @description('Required. The resource id of the private DNS zone.') - privateDnsZoneResourceId: string - }[] - }? - - @description('Optional. If Manual Private Link Connection is required.') - isManualConnection: bool? - - @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') - @maxLength(140) - manualConnectionRequestMessage: string? - - @description('Optional. Custom DNS configurations.') - customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') - fqdn: string? - - @description('Required. A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[]? - - @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') - ipConfigurations: { - @description('Required. The name of the resource that is unique within a resource group.') - name: string - - @description('Required. Properties of private endpoint IP configurations.') - properties: { - @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') - groupId: string - - @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') - memberName: string - - @description('Required. A private IP address obtained from the private endpoint\'s subnet.') - privateIPAddress: string - } - }[]? - - @description('Optional. Application security groups in which the private endpoint IP configuration is included.') - applicationSecurityGroupResourceIds: string[]? - - @description('Optional. The custom name of the network interface attached to the private endpoint.') - customNetworkInterfaceName: string? - - @description('Optional. Specify the type of lock.') - lock: lockType - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType - - @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') - tags: object? - - @description('Optional. Enable/Disable usage telemetry for module.') - enableTelemetry: bool? - - @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') - resourceGroupName: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to \'AllLogs\' to collect all logs.') - categoryGroup: string? - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @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.') - workspaceResourceId: string? - - @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.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? - -type customerManagedKeyType = { - @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') - keyVaultResourceId: string - - @description('Required. The name of the customer managed key to use for encryption.') - keyName: string - - @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') - keyVersion: string? - - @description('Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use.') - userAssignedIdentityResourceId: string? -}? - -type adminType = { +@export() +@description('The synapse workspace administrator\'s interface.') +type administratorType = { @description('Required. Workspace active directory administrator type.') administratorType: string @@ -640,8 +476,10 @@ type adminType = { @description('Optional. Tenant ID of the workspace active directory administrator.') @secure() tenantId: string? -}? +} +@export() +@description('The synapse workspace firewall rule\'s interface.') type firewallRuleType = { @description('Required. The name of the firewall rule.') name: string diff --git a/avm/res/synapse/workspace/main.json b/avm/res/synapse/workspace/main.json index a423ffb5a8..860caa8682 100644 --- a/avm/res/synapse/workspace/main.json +++ b/avm/res/synapse/workspace/main.json @@ -5,518 +5,583 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "3075067451671021037" + "version": "0.30.23.60470", + "templateHash": "14298198840929360566" }, "name": "Synapse Workspaces", "description": "This module deploys a Synapse Workspace.", "owner": "Azure/module-maintainers" }, "definitions": { - "managedIdentitiesType": { + "administratorType": { "type": "object", "properties": { - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, + "administratorType": { + "type": "string", + "metadata": { + "description": "Required. Workspace active directory administrator type." + } + }, + "login": { + "type": "securestring", + "metadata": { + "description": "Required. Login of the workspace active directory administrator." + } + }, + "sid": { + "type": "securestring", "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Required. Object ID of the workspace active directory administrator." + } + }, + "tenantId": { + "type": "securestring", + "nullable": true, + "metadata": { + "description": "Optional. Tenant ID of the workspace active directory administrator." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true, + "description": "The synapse workspace administrator's interface." + } }, - "lockType": { + "firewallRuleType": { "type": "object", "properties": { "name": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Required. The name of the firewall rule." } }, - "kind": { + "startIpAddress": { "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Required. The start IP address of the firewall rule. Must be IPv4 format." + } + }, + "endIpAddress": { + "type": "string", + "metadata": { + "description": "Required. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true, + "description": "The synapse workspace firewall rule's interface." + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } + "_1.privateEndpointCustomDnsConfigType": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "metadata": { - "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "privateDnsZoneGroup": { + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the Private DNS Zone Group." + "description": "Optional. The name of the private DNS Zone Group config." } }, - "privateDnsZoneGroupConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group config." - } - }, - "privateDnsZoneResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource id of the private DNS zone." - } - } - } - }, + "privateDnsZoneResourceId": { + "type": "string", "metadata": { - "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone group to configure for the private endpoint." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private IP addresses of the private endpoint." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private IP address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } + "description": "Required. The resource id of the private DNS zone." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } - }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." } }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." } } }, - "nullable": true + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "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." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a customer-managed key.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "customerManagedKeyType": { + "diagnosticSettingLogsOnlyType": { "type": "object", "properties": { - "keyVaultResourceId": { + "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + "description": "Optional. The name of diagnostic setting." } }, - "keyName": { + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "logAnalyticsDestinationType": { "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, "metadata": { - "description": "Required. The name of the customer managed key to use for encryption." + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." } }, - "keyVersion": { + "workspaceResourceId": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + "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." } }, - "userAssignedIdentityResourceId": { + "storageAccountResourceId": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if only logs are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "adminType": { + "lockType": { "type": "object", "properties": { - "administratorType": { + "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. Workspace active directory administrator type." + "description": "Optional. Specify the name of lock." } }, - "login": { - "type": "securestring", + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, "metadata": { - "description": "Required. Login of the workspace active directory administrator." + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "managedIdentityOnlyUserAssignedType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "privateEndpointMultiServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." } }, - "sid": { - "type": "securestring", + "location": { + "type": "string", + "nullable": true, "metadata": { - "description": "Required. Object ID of the workspace active directory administrator." + "description": "Optional. The location to deploy the private endpoint to." } }, - "tenantId": { - "type": "securestring", + "privateLinkServiceConnectionName": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Tenant ID of the workspace active directory administrator." + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "metadata": { + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\" for a Storage Account's Private Endpoints." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can NOT be assumed (i.e., for services that have more than one subresource, like Storage Account with Blob (blob, table, queue, file, ...).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, - "firewallRuleType": { + "roleAssignmentType": { "type": "object", "properties": { "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The name of the firewall rule." + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "startIpAddress": { + "roleDefinitionIdOrName": { "type": "string", "metadata": { - "description": "Required. The start IP address of the firewall rule. Must be IPv4 format." + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, - "endIpAddress": { + "principalId": { "type": "string", "metadata": { - "description": "Required. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress." + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } } } }, @@ -583,13 +648,15 @@ } }, "administrator": { - "$ref": "#/definitions/adminType", + "$ref": "#/definitions/administratorType", + "nullable": true, "metadata": { "description": "Optional. The Entra ID administrator for the synapse workspace." } }, "customerManagedKey": { "$ref": "#/definitions/customerManagedKeyType", + "nullable": true, "metadata": { "description": "Optional. The customer managed key definition." } @@ -700,31 +767,45 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityOnlyUserAssignedType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointMultiServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingLogsOnlyType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } @@ -917,7 +998,9 @@ "type": { "value": "[parameters('integrationRuntimes')[copyIndex()].type]" }, - "typeProperties": "[if(contains(parameters('integrationRuntimes')[copyIndex()], 'typeProperties'), createObject('value', parameters('integrationRuntimes')[copyIndex()].typeProperties), createObject('value', createObject()))]" + "typeProperties": { + "value": "[coalesce(tryGet(parameters('integrationRuntimes')[copyIndex()], 'typeProperties'), createObject())]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -925,8 +1008,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4134219125418987684" + "version": "0.30.23.60470", + "templateHash": "2875700223215345190" }, "name": "Synapse Workspace Integration Runtimes", "description": "This module deploys a Synapse Workspace Integration Runtime.", @@ -1023,8 +1106,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4045748488403006026" + "version": "0.30.23.60470", + "templateHash": "6457069339265019781" } }, "parameters": { @@ -1111,8 +1194,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6170014210030770909" + "version": "0.30.23.60470", + "templateHash": "15229329511207297146" }, "name": "Synapse Workspaces Keys", "description": "This module deploys a Synapse Workspaces Key.", @@ -1219,8 +1302,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "15890618337043813918" + "version": "0.30.23.60470", + "templateHash": "11234358964964275645" }, "name": "Synapse Workspaces Administrators", "description": "This module deploys Synapse Workspaces Administrators.", @@ -1334,8 +1417,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6729418057172891787" + "version": "0.30.23.60470", + "templateHash": "1410907925603155251" }, "name": "Synapse Workspaces Firewall Rules", "description": "This module deploys Synapse Workspaces Firewall Rules.", diff --git a/avm/res/virtual-machine-images/image-template/README.md b/avm/res/virtual-machine-images/image-template/README.md index 22bfaaa10a..139856eedf 100644 --- a/avm/res/virtual-machine-images/image-template/README.md +++ b/avm/res/virtual-machine-images/image-template/README.md @@ -8,6 +8,7 @@ This module deploys a Virtual Machine Image Template that can be consumed by Azu - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Notes](#Notes) - [Data Collection](#Data-Collection) @@ -749,7 +750,7 @@ param tags = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`baseTime`](#parameter-basetime) | string | Do not provide a value! This date value is used to generate a unique image template name. | +| [`baseTime`](#parameter-basetime) | string | Do not provide a value! This date is used to generate a unique image template name. | ### Parameter: `distributions` @@ -782,7 +783,7 @@ The managed identity definition for this resource. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. -- Required: Yes +- Required: No - Type: array ### Parameter: `name` @@ -1157,7 +1158,7 @@ List of User-Assigned Identities associated to the Build VM for accessing Azure ### Parameter: `baseTime` -Do not provide a value! This date value is used to generate a unique image template name. +Do not provide a value! This date is used to generate a unique image template name. - Required: No - Type: string @@ -1174,6 +1175,14 @@ Do not provide a value! This date value is used to generate a unique image templ | `resourceId` | string | The resource ID of the image template. | | `runThisCommand` | string | The command to run in order to trigger the image build. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Notes ### Parameter Usage: `imageSource` diff --git a/avm/res/virtual-machine-images/image-template/main.bicep b/avm/res/virtual-machine-images/image-template/main.bicep index 6d68abacc9..e7f7de9f07 100644 --- a/avm/res/virtual-machine-images/image-template/main.bicep +++ b/avm/res/virtual-machine-images/image-template/main.bicep @@ -31,20 +31,22 @@ param customizationSteps array? @description('Optional. Resource ID of the staging resource group in the same subscription and location as the image template that will be used to build the image.

    If this field is empty, a resource group with a random name will be created.

    If the resource group specified in this field doesn\'t exist, it will be created with the same name.

    If the resource group specified exists, it must be empty and in the same region as the image template.

    The resource group created will be deleted during template deletion if this field is empty or the resource group specified doesn\'t exist,

    but if the resource group specified exists the resources created in the resource group will be deleted during template deletion and the resource group itself will remain.') param stagingResourceGroupResourceId string? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? @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.') +@description('Generated. Do not provide a value! This date is used to generate a unique image template name.') param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Required. The distribution targets where the image output needs to go to.') param distributions distributionType[] @@ -52,11 +54,12 @@ param distributions distributionType[] @description('Optional. List of User-Assigned Identities associated to the Build VM for accessing Azure resources such as Key Vaults from your customizer scripts. Be aware, the user assigned identities specified in the \'managedIdentities\' parameter must have the \'Managed Identity Operator\' role assignment on all the user assigned identities specified in this parameter for Azure Image Builder to be able to associate them to the build VM.') param vmUserAssignedIdentities array = [] +import { managedIdentityOnlyUserAssignedType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Required. The managed identity definition for this resource.') -param managedIdentities managedIdentitiesType +param managedIdentities managedIdentityOnlyUserAssignedType @description('Optional. Configuration options and list of validations to be performed on the resulting image.') -param validationProcess validationProcessType +param validationProcess validationProcessType? @allowed([ 'Enabled' @@ -182,6 +185,7 @@ resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2023-07-01 : {}) ) ] + #disable-next-line BCP225 // The discriminator property "type" value cannot be determined at compilation time. - which is fine validate: validationProcess optimize: optimizeVmBoot != null ? { @@ -242,48 +246,11 @@ output location string = imageTemplate.location // Definitions // // =============== // -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type managedIdentitiesType = { - @description('Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption.') - userAssignedResourceIds: string[] -} - +@export() @discriminator('type') type distributionType = sharedImageDistributionType | managedImageDistributionType | unManagedDistributionType +@export() type sharedImageDistributionType = { @description('Optional. The name to be used for the associated RunOutput. If not provided, a name will be calculated.') runOutputName: string? @@ -310,6 +277,7 @@ type sharedImageDistributionType = { storageAccountType: ('Standard_LRS' | 'Standard_ZRS')? } +@export() type unManagedDistributionType = { @description('Required. The type of distribution.') type: 'VHD' @@ -324,6 +292,7 @@ type unManagedDistributionType = { imageName: string } +@export() type managedImageDistributionType = { @description('Required. The type of distribution.') type: 'ManagedImage' @@ -344,6 +313,7 @@ type managedImageDistributionType = { imageName: string } +@export() type validationProcessType = { @description('Optional. If validation fails and this field is set to false, output image(s) will not be distributed. This is the default behavior. If validation fails and this field is set to true, output image(s) will still be distributed. Please use this option with caution as it may result in bad images being distributed for use. In either case (true or false), the end to end image run will be reported as having failed in case of a validation failure. [Note: This field has no effect if validation succeeds.].') continueDistributeOnFailure: bool? @@ -383,4 +353,4 @@ type validationProcessType = { @description('Optional. If this field is set to true, the image specified in the \'source\' section will directly be validated. No separate build will be run to generate and then validate a customized image. Not supported when performing customizations, validations or distributions on the image.') sourceValidationOnly: bool? -}? +} diff --git a/avm/res/virtual-machine-images/image-template/main.json b/avm/res/virtual-machine-images/image-template/main.json index 8a2d773d7c..bd36673878 100644 --- a/avm/res/virtual-machine-images/image-template/main.json +++ b/avm/res/virtual-machine-images/image-template/main.json @@ -5,126 +5,14 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "7173338220381253397" + "version": "0.30.23.60470", + "templateHash": "9021236296601587261" }, "name": "Virtual Machine Image Templates", "description": "This module deploys a Virtual Machine Image Template that can be consumed by Azure Image Builder (AIB).", "owner": "Azure/module-maintainers" }, "definitions": { - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "managedIdentitiesType": { - "type": "object", - "properties": { - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." - } - } - } - }, "distributionType": { "type": "object", "discriminator": { @@ -140,6 +28,9 @@ "$ref": "#/definitions/unManagedDistributionType" } } + }, + "metadata": { + "__bicep_export!": true } }, "sharedImageDistributionType": { @@ -209,6 +100,9 @@ "description": "Optional. The storage account type of the image. Defaults to [Standard_LRS]." } } + }, + "metadata": { + "__bicep_export!": true } }, "unManagedDistributionType": { @@ -243,6 +137,9 @@ "description": "Conditional. Name of the managed or unmanaged image that will be created." } } + }, + "metadata": { + "__bicep_export!": true } }, "managedImageDistributionType": { @@ -291,6 +188,9 @@ "description": "Conditional. Name of the managed or unmanaged image that will be created." } } + }, + "metadata": { + "__bicep_export!": true } }, "validationProcessType": { @@ -403,7 +303,135 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "managedIdentityOnlyUserAssignedType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -472,6 +500,7 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } @@ -487,7 +516,7 @@ "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." + "description": "Generated. Do not provide a value! This date is used to generate a unique image template name." } }, "enableTelemetry": { @@ -498,7 +527,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -520,13 +553,14 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityOnlyUserAssignedType", "metadata": { "description": "Required. The managed identity definition for this resource." } }, "validationProcess": { "$ref": "#/definitions/validationProcessType", + "nullable": true, "metadata": { "description": "Optional. Configuration options and list of validations to be performed on the resulting image." } diff --git a/avm/res/web/connection/README.md b/avm/res/web/connection/README.md index a192ce132b..abc60ff2d9 100644 --- a/avm/res/web/connection/README.md +++ b/avm/res/web/connection/README.md @@ -13,6 +13,7 @@ This module deploys an Azure API Connection. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types @@ -687,6 +688,14 @@ Links to test the API connection. | `resourceGroupName` | string | The resource group the connection was deployed into. | | `resourceId` | string | The resource ID of the connection. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.2.1` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/web/connection/main.bicep b/avm/res/web/connection/main.bicep index db51edfc25..a3f8796030 100644 --- a/avm/res/web/connection/main.bicep +++ b/avm/res/web/connection/main.bicep @@ -76,14 +76,16 @@ param parameterValues object? }) param parameterValueSet object? +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType +param roleAssignments roleAssignmentType[]? @description('Optional. The status of the connection.') param statuses object[]? +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' @description('Optional. The lock settings of the service.') -param lock lockType +param lock lockType? @metadata({ example: ''' @@ -206,41 +208,3 @@ output name string = connection.name @description('The location the resource was deployed into.') output location string = connection.location - -// =============== // -// Definitions // -// =============== // - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') - name: string? - - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/web/connection/main.json b/avm/res/web/connection/main.json index 0d5894685a..86912a1993 100644 --- a/avm/res/web/connection/main.json +++ b/avm/res/web/connection/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "1429787560788637007" + "version": "0.30.23.60470", + "templateHash": "15595731517219272130" }, "name": "API Connections", "description": "This module deploys an Azure API Connection.", @@ -36,80 +36,87 @@ } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } }, "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." - } - }, - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } } }, "parameters": { @@ -178,7 +185,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -195,6 +206,7 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } diff --git a/avm/res/web/hosting-environment/README.md b/avm/res/web/hosting-environment/README.md index d47314ce86..8866773fca 100644 --- a/avm/res/web/hosting-environment/README.md +++ b/avm/res/web/hosting-environment/README.md @@ -17,8 +17,8 @@ This module deploys an App Service Environment. | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | -| `Microsoft.Web/hostingEnvironments` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-03-01/hostingEnvironments) | -| `Microsoft.Web/hostingEnvironments/configurations` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/hostingEnvironments/configurations) | +| `Microsoft.Web/hostingEnvironments` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/hostingEnvironments) | +| `Microsoft.Web/hostingEnvironments/configurations` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/hostingEnvironments/configurations) | ## Usage examples @@ -49,7 +49,6 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' name: 'whemin001' subnetResourceId: '' // Non-required parameters - kind: 'ASEv3' location: '' } } @@ -75,9 +74,6 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' "value": "" }, // Non-required parameters - "kind": { - "value": "ASEv3" - }, "location": { "value": "" } @@ -99,7 +95,6 @@ using 'br/public:avm/res/web/hosting-environment:' param name = 'whemin001' param subnetResourceId = '' // Non-required parameters -param kind = 'ASEv3' param location = '' ``` @@ -123,7 +118,6 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' name: 'whemax001' subnetResourceId: '' // Non-required parameters - allowNewPrivateEndpointConnections: true clusterSettings: [ { name: 'DisableTls1.0' @@ -142,9 +136,8 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' workspaceResourceId: '' } ] - ftpEnabled: true - inboundIpAddressOverride: '10.0.0.10' internalLoadBalancingMode: 'Web, Publishing' + kind: 'ASEv3' location: '' lock: { kind: 'CanNotDelete' @@ -156,14 +149,23 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' '' ] } - remoteDebugEnabled: true + networkConfiguration: { + properties: { + allowNewPrivateEndpointConnections: true + ftpEnabled: true + inboundIpAddressOverride: '10.0.0.10' + remoteDebugEnabled: true + } + } roleAssignments: [ { + name: '97fc1da9-bfe4-409d-b17a-da9a82fad0d0' principalId: '' principalType: 'ServicePrincipal' roleDefinitionIdOrName: 'Owner' } { + name: '' principalId: '' principalType: 'ServicePrincipal' roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' @@ -180,6 +182,7 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' resourceType: 'App Service Environment' } upgradePreference: 'Late' + zoneRedundant: true } } ``` @@ -204,9 +207,6 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' "value": "" }, // Non-required parameters - "allowNewPrivateEndpointConnections": { - "value": true - }, "clusterSettings": { "value": [ { @@ -235,15 +235,12 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' } ] }, - "ftpEnabled": { - "value": true - }, - "inboundIpAddressOverride": { - "value": "10.0.0.10" - }, "internalLoadBalancingMode": { "value": "Web, Publishing" }, + "kind": { + "value": "ASEv3" + }, "location": { "value": "" }, @@ -261,17 +258,26 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' ] } }, - "remoteDebugEnabled": { - "value": true + "networkConfiguration": { + "value": { + "properties": { + "allowNewPrivateEndpointConnections": true, + "ftpEnabled": true, + "inboundIpAddressOverride": "10.0.0.10", + "remoteDebugEnabled": true + } + } }, "roleAssignments": { "value": [ { + "name": "97fc1da9-bfe4-409d-b17a-da9a82fad0d0", "principalId": "", "principalType": "ServicePrincipal", "roleDefinitionIdOrName": "Owner" }, { + "name": "", "principalId": "", "principalType": "ServicePrincipal", "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" @@ -292,6 +298,9 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' }, "upgradePreference": { "value": "Late" + }, + "zoneRedundant": { + "value": true } } } @@ -311,7 +320,6 @@ using 'br/public:avm/res/web/hosting-environment:' param name = 'whemax001' param subnetResourceId = '' // Non-required parameters -param allowNewPrivateEndpointConnections = true param clusterSettings = [ { name: 'DisableTls1.0' @@ -330,9 +338,8 @@ param diagnosticSettings = [ workspaceResourceId: '' } ] -param ftpEnabled = true -param inboundIpAddressOverride = '10.0.0.10' param internalLoadBalancingMode = 'Web, Publishing' +param kind = 'ASEv3' param location = '' param lock = { kind: 'CanNotDelete' @@ -344,14 +351,23 @@ param managedIdentities = { '' ] } -param remoteDebugEnabled = true +param networkConfiguration = { + properties: { + allowNewPrivateEndpointConnections: true + ftpEnabled: true + inboundIpAddressOverride: '10.0.0.10' + remoteDebugEnabled: true + } +} param roleAssignments = [ { + name: '97fc1da9-bfe4-409d-b17a-da9a82fad0d0' principalId: '' principalType: 'ServicePrincipal' roleDefinitionIdOrName: 'Owner' } { + name: '' principalId: '' principalType: 'ServicePrincipal' roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' @@ -368,6 +384,7 @@ param tags = { resourceType: 'App Service Environment' } param upgradePreference = 'Late' +param zoneRedundant = true ``` @@ -390,7 +407,6 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' name: 'whewaf001' subnetResourceId: '' // Non-required parameters - allowNewPrivateEndpointConnections: true clusterSettings: [ { name: 'DisableTls1.0' @@ -409,8 +425,6 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' workspaceResourceId: '' } ] - ftpEnabled: true - inboundIpAddressOverride: '10.0.0.10' internalLoadBalancingMode: 'Web, Publishing' location: '' managedIdentities: { @@ -419,7 +433,13 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' '' ] } - remoteDebugEnabled: true + networkConfiguration: { + properties: { + allowNewPrivateEndpointConnections: true + ftpEnabled: true + remoteDebugEnabled: true + } + } tags: { 'hidden-title': 'This is visible in the resource name' hostingEnvironmentName: 'whewaf001' @@ -450,9 +470,6 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' "value": "" }, // Non-required parameters - "allowNewPrivateEndpointConnections": { - "value": true - }, "clusterSettings": { "value": [ { @@ -481,12 +498,6 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' } ] }, - "ftpEnabled": { - "value": true - }, - "inboundIpAddressOverride": { - "value": "10.0.0.10" - }, "internalLoadBalancingMode": { "value": "Web, Publishing" }, @@ -501,8 +512,14 @@ module hostingEnvironment 'br/public:avm/res/web/hosting-environment:' ] } }, - "remoteDebugEnabled": { - "value": true + "networkConfiguration": { + "value": { + "properties": { + "allowNewPrivateEndpointConnections": true, + "ftpEnabled": true, + "remoteDebugEnabled": true + } + } }, "tags": { "value": { @@ -532,7 +549,6 @@ using 'br/public:avm/res/web/hosting-environment:' param name = 'whewaf001' param subnetResourceId = '' // Non-required parameters -param allowNewPrivateEndpointConnections = true param clusterSettings = [ { name: 'DisableTls1.0' @@ -551,8 +567,6 @@ param diagnosticSettings = [ workspaceResourceId: '' } ] -param ftpEnabled = true -param inboundIpAddressOverride = '10.0.0.10' param internalLoadBalancingMode = 'Web, Publishing' param location = '' param managedIdentities = { @@ -561,7 +575,13 @@ param managedIdentities = { '' ] } -param remoteDebugEnabled = true +param networkConfiguration = { + properties: { + allowNewPrivateEndpointConnections: true + ftpEnabled: true + remoteDebugEnabled: true + } +} param tags = { 'hidden-title': 'This is visible in the resource name' hostingEnvironmentName: 'whewaf001' @@ -586,7 +606,6 @@ param upgradePreference = 'Late' | Parameter | Type | Description | | :-- | :-- | :-- | -| [`allowNewPrivateEndpointConnections`](#parameter-allownewprivateendpointconnections) | bool | Property to enable and disable new private endpoint connection creation on ASE. | | [`clusterSettings`](#parameter-clustersettings) | array | Custom settings for changing the behavior of the App Service Environment. | | [`customDnsSuffix`](#parameter-customdnssuffix) | string | Enable the default custom domain suffix to use for all sites deployed on the ASE. If provided, then customDnsSuffixCertificateUrl and customDnsSuffixKeyVaultReferenceIdentity are required. | | [`customDnsSuffixCertificateUrl`](#parameter-customdnssuffixcertificateurl) | string | The URL referencing the Azure Key Vault certificate secret that should be used as the default SSL/TLS certificate for sites with the custom domain suffix. Required if customDnsSuffix is not empty. | @@ -596,14 +615,12 @@ param upgradePreference = 'Late' | [`dnsSuffix`](#parameter-dnssuffix) | string | DNS suffix of the App Service Environment. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`frontEndScaleFactor`](#parameter-frontendscalefactor) | int | Scale factor for frontends. | -| [`ftpEnabled`](#parameter-ftpenabled) | bool | Property to enable and disable FTP on ASEV3. | -| [`inboundIpAddressOverride`](#parameter-inboundipaddressoverride) | string | Customer provided Inbound IP Address. Only able to be set on Ase create. | | [`internalLoadBalancingMode`](#parameter-internalloadbalancingmode) | string | Specifies which endpoints to serve internally in the Virtual Network for the App Service Environment. - None, Web, Publishing, Web,Publishing. "None" Exposes the ASE-hosted apps on an internet-accessible IP address. | | [`kind`](#parameter-kind) | string | Kind of resource. | | [`location`](#parameter-location) | string | Location for all Resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | -| [`remoteDebugEnabled`](#parameter-remotedebugenabled) | bool | Property to enable and disable Remote Debug on ASEv3. | +| [`networkConfiguration`](#parameter-networkconfiguration) | object | Properties to configure additional networking features. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | | [`tags`](#parameter-tags) | object | Tags of the resource. | | [`upgradePreference`](#parameter-upgradepreference) | string | Specify preference for when and how the planned maintenance is applied. | @@ -623,14 +640,6 @@ ResourceId for the subnet. - Required: Yes - Type: string -### Parameter: `allowNewPrivateEndpointConnections` - -Property to enable and disable new private endpoint connection creation on ASE. - -- Required: No -- Type: bool -- Default: `False` - ### Parameter: `clusterSettings` Custom settings for changing the behavior of the App Service Environment. @@ -807,22 +816,6 @@ Scale factor for frontends. - Type: int - Default: `15` -### Parameter: `ftpEnabled` - -Property to enable and disable FTP on ASEV3. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `inboundIpAddressOverride` - -Customer provided Inbound IP Address. Only able to be set on Ase create. - -- Required: No -- Type: string -- Default: `''` - ### Parameter: `internalLoadBalancingMode` Specifies which endpoints to serve internally in the Virtual Network for the App Service Environment. - None, Web, Publishing, Web,Publishing. "None" Exposes the ASE-hosted apps on an internet-accessible IP address. @@ -926,13 +919,12 @@ The resource ID(s) to assign to the resource. - Required: No - Type: array -### Parameter: `remoteDebugEnabled` +### Parameter: `networkConfiguration` -Property to enable and disable Remote Debug on ASEv3. +Properties to configure additional networking features. - Required: No -- Type: bool -- Default: `False` +- Type: object ### Parameter: `roleAssignments` @@ -962,6 +954,7 @@ Array of role assignments to create. | [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | | [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | | [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`name`](#parameter-roleassignmentsname) | string | The name (as GUID) of the role assignment. If not provided, a GUID will be generated. | | [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | ### Parameter: `roleAssignments.principalId` @@ -1012,6 +1005,13 @@ The description of the role assignment. - Required: No - Type: string +### Parameter: `roleAssignments.name` + +The name (as GUID) of the role assignment. If not provided, a GUID will be generated. + +- Required: No +- Type: string + ### Parameter: `roleAssignments.principalType` The principal type of the assigned principal ID. @@ -1059,7 +1059,7 @@ Switch to make the App Service Environment zone redundant. If enabled, the minim - Required: No - Type: bool -- Default: `False` +- Default: `True` ## Outputs diff --git a/avm/res/web/hosting-environment/configuration--customdnssuffix/README.md b/avm/res/web/hosting-environment/configuration--customdnssuffix/README.md index aa95a8c71f..c49c8106ac 100644 --- a/avm/res/web/hosting-environment/configuration--customdnssuffix/README.md +++ b/avm/res/web/hosting-environment/configuration--customdnssuffix/README.md @@ -12,7 +12,7 @@ This module deploys a Hosting Environment Custom DNS Suffix Configuration. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/hostingEnvironments/configurations` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/hostingEnvironments/configurations) | +| `Microsoft.Web/hostingEnvironments/configurations` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/hostingEnvironments/configurations) | ## Parameters diff --git a/avm/res/web/hosting-environment/configuration--customdnssuffix/main.bicep b/avm/res/web/hosting-environment/configuration--customdnssuffix/main.bicep index ecef282dd0..5d618cc831 100644 --- a/avm/res/web/hosting-environment/configuration--customdnssuffix/main.bicep +++ b/avm/res/web/hosting-environment/configuration--customdnssuffix/main.bicep @@ -18,7 +18,7 @@ resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2022-03-01' ex name: hostingEnvironmentName } -resource configuration 'Microsoft.Web/hostingEnvironments/configurations@2022-03-01' = { +resource configuration 'Microsoft.Web/hostingEnvironments/configurations@2023-12-01' = { name: 'customdnssuffix' parent: appServiceEnvironment properties: { diff --git a/avm/res/web/hosting-environment/configuration--customdnssuffix/main.json b/avm/res/web/hosting-environment/configuration--customdnssuffix/main.json index a38860abbc..0436558384 100644 --- a/avm/res/web/hosting-environment/configuration--customdnssuffix/main.json +++ b/avm/res/web/hosting-environment/configuration--customdnssuffix/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "12791869385776671140" + "version": "0.30.3.12046", + "templateHash": "8555887239478847203" }, "name": "Hosting Environment Custom DNS Suffix Configuration", "description": "This module deploys a Hosting Environment Custom DNS Suffix Configuration.", @@ -40,7 +40,7 @@ "resources": [ { "type": "Microsoft.Web/hostingEnvironments/configurations", - "apiVersion": "2022-03-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('hostingEnvironmentName'), 'customdnssuffix')]", "properties": { "certificateUrl": "[parameters('certificateUrl')]", diff --git a/avm/res/web/hosting-environment/configuration--networking/README.md b/avm/res/web/hosting-environment/configuration--networking/README.md deleted file mode 100644 index 04c0307304..0000000000 --- a/avm/res/web/hosting-environment/configuration--networking/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# Hosting Environment Network Configuration `[Microsoft.Web/hostingEnvironments/configurations]` - -This module deploys a Hosting Environment Network Configuration. - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.Web/hostingEnvironments/configurations` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/hostingEnvironments/configurations) | - -## Parameters - -**Conditional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`hostingEnvironmentName`](#parameter-hostingenvironmentname) | string | The name of the parent Hosting Environment. Required if the template is used in a standalone deployment. | - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`allowNewPrivateEndpointConnections`](#parameter-allownewprivateendpointconnections) | bool | Property to enable and disable new private endpoint connection creation on ASE. | -| [`ftpEnabled`](#parameter-ftpenabled) | bool | Property to enable and disable FTP on ASEV3. | -| [`inboundIpAddressOverride`](#parameter-inboundipaddressoverride) | string | Customer provided Inbound IP Address. Only able to be set on Ase create. | -| [`remoteDebugEnabled`](#parameter-remotedebugenabled) | bool | Property to enable and disable Remote Debug on ASEv3. | - -### Parameter: `hostingEnvironmentName` - -The name of the parent Hosting Environment. Required if the template is used in a standalone deployment. - -- Required: Yes -- Type: string - -### Parameter: `allowNewPrivateEndpointConnections` - -Property to enable and disable new private endpoint connection creation on ASE. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `ftpEnabled` - -Property to enable and disable FTP on ASEV3. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `inboundIpAddressOverride` - -Customer provided Inbound IP Address. Only able to be set on Ase create. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `remoteDebugEnabled` - -Property to enable and disable Remote Debug on ASEv3. - -- Required: No -- Type: bool -- Default: `False` - -## Outputs - -| Output | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the configuration. | -| `resourceGroupName` | string | The resource group of the deployed configuration. | -| `resourceId` | string | The resource ID of the deployed configuration. | diff --git a/avm/res/web/hosting-environment/configuration--networking/main.bicep b/avm/res/web/hosting-environment/configuration--networking/main.bicep deleted file mode 100644 index d5caa2f412..0000000000 --- a/avm/res/web/hosting-environment/configuration--networking/main.bicep +++ /dev/null @@ -1,42 +0,0 @@ -metadata name = 'Hosting Environment Network Configuration' -metadata description = 'This module deploys a Hosting Environment Network Configuration.' -metadata owner = 'Azure/module-maintainers' - -@description('Conditional. The name of the parent Hosting Environment. Required if the template is used in a standalone deployment.') -param hostingEnvironmentName string - -@description('Optional. Property to enable and disable new private endpoint connection creation on ASE.') -param allowNewPrivateEndpointConnections bool = false - -@description('Optional. Property to enable and disable FTP on ASEV3.') -param ftpEnabled bool = false - -@description('Optional. Customer provided Inbound IP Address. Only able to be set on Ase create.') -param inboundIpAddressOverride string = '' - -@description('Optional. Property to enable and disable Remote Debug on ASEv3.') -param remoteDebugEnabled bool = false - -resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2022-03-01' existing = { - name: hostingEnvironmentName -} - -resource configuration 'Microsoft.Web/hostingEnvironments/configurations@2022-03-01' = { - name: 'networking' - parent: appServiceEnvironment - properties: { - allowNewPrivateEndpointConnections: allowNewPrivateEndpointConnections - ftpEnabled: ftpEnabled - inboundIpAddressOverride: inboundIpAddressOverride - remoteDebugEnabled: remoteDebugEnabled - } -} - -@description('The name of the configuration.') -output name string = configuration.name - -@description('The resource ID of the deployed configuration.') -output resourceId string = configuration.id - -@description('The resource group of the deployed configuration.') -output resourceGroupName string = resourceGroup().name diff --git a/avm/res/web/hosting-environment/configuration--networking/main.json b/avm/res/web/hosting-environment/configuration--networking/main.json deleted file mode 100644 index 8f81ea2338..0000000000 --- a/avm/res/web/hosting-environment/configuration--networking/main.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "17598276744130339630" - }, - "name": "Hosting Environment Network Configuration", - "description": "This module deploys a Hosting Environment Network Configuration.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "hostingEnvironmentName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent Hosting Environment. Required if the template is used in a standalone deployment." - } - }, - "allowNewPrivateEndpointConnections": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Property to enable and disable new private endpoint connection creation on ASE." - } - }, - "ftpEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Property to enable and disable FTP on ASEV3." - } - }, - "inboundIpAddressOverride": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Customer provided Inbound IP Address. Only able to be set on Ase create." - } - }, - "remoteDebugEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Property to enable and disable Remote Debug on ASEv3." - } - } - }, - "resources": [ - { - "type": "Microsoft.Web/hostingEnvironments/configurations", - "apiVersion": "2022-03-01", - "name": "[format('{0}/{1}', parameters('hostingEnvironmentName'), 'networking')]", - "properties": { - "allowNewPrivateEndpointConnections": "[parameters('allowNewPrivateEndpointConnections')]", - "ftpEnabled": "[parameters('ftpEnabled')]", - "inboundIpAddressOverride": "[parameters('inboundIpAddressOverride')]", - "remoteDebugEnabled": "[parameters('remoteDebugEnabled')]" - } - } - ], - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the configuration." - }, - "value": "networking" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the deployed configuration." - }, - "value": "[resourceId('Microsoft.Web/hostingEnvironments/configurations', parameters('hostingEnvironmentName'), 'networking')]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The resource group of the deployed configuration." - }, - "value": "[resourceGroup().name]" - } - } -} \ No newline at end of file diff --git a/avm/res/web/hosting-environment/main.bicep b/avm/res/web/hosting-environment/main.bicep index e0d4b7ead3..5a1563ef60 100644 --- a/avm/res/web/hosting-environment/main.bicep +++ b/avm/res/web/hosting-environment/main.bicep @@ -65,17 +65,8 @@ param frontEndScaleFactor int = 15 ]) param internalLoadBalancingMode string = 'None' -@description('Optional. Property to enable and disable new private endpoint connection creation on ASE.') -param allowNewPrivateEndpointConnections bool = false - -@description('Optional. Property to enable and disable FTP on ASEV3.') -param ftpEnabled bool = false - -@description('Optional. Customer provided Inbound IP Address. Only able to be set on Ase create.') -param inboundIpAddressOverride string = '' - -@description('Optional. Property to enable and disable Remote Debug on ASEv3.') -param remoteDebugEnabled bool = false +@description('Optional. Properties to configure additional networking features.') +param networkConfiguration object? @description('Optional. Specify preference for when and how the planned maintenance is applied.') @allowed([ @@ -90,7 +81,7 @@ param upgradePreference string = 'None' param subnetResourceId string @description('Optional. Switch to make the App Service Environment zone redundant. If enabled, the minimum App Service plan instance count will be three, otherwise 1. If enabled, the `dedicatedHostCount` must be set to `-1`.') -param zoneRedundant bool = false +param zoneRedundant bool = true @description('Optional. The managed identity definition for this resource.') param managedIdentities managedIdentitiesType @@ -127,6 +118,17 @@ var builtInRoleNames = { ) } +var formattedRoleAssignments = [ + for (roleAssignment, index) in (roleAssignments ?? []): union(roleAssignment, { + roleDefinitionId: builtInRoleNames[?roleAssignment.roleDefinitionIdOrName] ?? (contains( + roleAssignment.roleDefinitionIdOrName, + '/providers/Microsoft.Authorization/roleDefinitions/' + ) + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) + }) +] + // ============== // // Resources // // ============== // @@ -150,7 +152,7 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableT } } -resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2022-03-01' = { +resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2023-12-01' = { name: name kind: kind location: location @@ -163,6 +165,7 @@ resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2022-03-01' = frontEndScaleFactor: frontEndScaleFactor internalLoadBalancingMode: internalLoadBalancingMode upgradePreference: upgradePreference + networkingConfiguration: networkConfiguration virtualNetwork: { id: subnetResourceId subnet: last(split(subnetResourceId, '/')) @@ -171,17 +174,6 @@ resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2022-03-01' = } } -module appServiceEnvironment_configurations_networking 'configuration--networking/main.bicep' = { - name: '${uniqueString(deployment().name, location)}-AppServiceEnv-Configurations-Networking' - params: { - hostingEnvironmentName: appServiceEnvironment.name - allowNewPrivateEndpointConnections: allowNewPrivateEndpointConnections - ftpEnabled: ftpEnabled - inboundIpAddressOverride: inboundIpAddressOverride - remoteDebugEnabled: remoteDebugEnabled - } -} - module appServiceEnvironment_configurations_customDnsSuffix 'configuration--customdnssuffix/main.bicep' = if (!empty(customDnsSuffix)) { name: '${uniqueString(deployment().name, location)}-AppServiceEnv-Configurations-CustomDnsSuffix' params: { @@ -226,14 +218,14 @@ resource appServiceEnvironment_diagnosticSettings 'Microsoft.Insights/diagnostic ] resource appServiceEnvironment_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ - for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(appServiceEnvironment.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + for (roleAssignment, index) in (formattedRoleAssignments ?? []): { + name: roleAssignment.?name ?? guid( + appServiceEnvironment.id, + roleAssignment.principalId, + roleAssignment.roleDefinitionId + ) properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) - ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] - : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') - ? roleAssignment.roleDefinitionIdOrName - : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + roleDefinitionId: roleAssignment.roleDefinitionId principalId: roleAssignment.principalId description: roleAssignment.?description principalType: roleAssignment.?principalType @@ -244,7 +236,6 @@ resource appServiceEnvironment_roleAssignments 'Microsoft.Authorization/roleAssi scope: appServiceEnvironment } ] - // ============ // // Outputs // // ============ // @@ -285,6 +276,9 @@ type lockType = { }? type roleAssignmentType = { + @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') + name: string? + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') roleDefinitionIdOrName: string diff --git a/avm/res/web/hosting-environment/main.json b/avm/res/web/hosting-environment/main.json index d88ccda41e..c61a3639bf 100644 --- a/avm/res/web/hosting-environment/main.json +++ b/avm/res/web/hosting-environment/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "8502699681800446441" + "version": "0.30.3.12046", + "templateHash": "6878502945321787269" }, "name": "App Service Environments", "description": "This module deploys an App Service Environment.", @@ -66,6 +66,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -333,32 +340,11 @@ "description": "Optional. Specifies which endpoints to serve internally in the Virtual Network for the App Service Environment. - None, Web, Publishing, Web,Publishing. \"None\" Exposes the ASE-hosted apps on an internet-accessible IP address." } }, - "allowNewPrivateEndpointConnections": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Property to enable and disable new private endpoint connection creation on ASE." - } - }, - "ftpEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Property to enable and disable FTP on ASEV3." - } - }, - "inboundIpAddressOverride": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Customer provided Inbound IP Address. Only able to be set on Ase create." - } - }, - "remoteDebugEnabled": { - "type": "bool", - "defaultValue": false, + "networkConfiguration": { + "type": "object", + "nullable": true, "metadata": { - "description": "Optional. Property to enable and disable Remote Debug on ASEv3." + "description": "Optional. Properties to configure additional networking features." } }, "upgradePreference": { @@ -382,7 +368,7 @@ }, "zoneRedundant": { "type": "bool", - "defaultValue": false, + "defaultValue": true, "metadata": { "description": "Optional. Switch to make the App Service Environment zone redundant. If enabled, the minimum App Service plan instance count will be three, otherwise 1. If enabled, the `dedicatedHostCount` must be set to `-1`." } @@ -401,6 +387,13 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", "builtInRoleNames": { @@ -434,7 +427,7 @@ }, "appServiceEnvironment": { "type": "Microsoft.Web/hostingEnvironments", - "apiVersion": "2022-03-01", + "apiVersion": "2023-12-01", "name": "[parameters('name')]", "kind": "[parameters('kind')]", "location": "[parameters('location')]", @@ -447,6 +440,7 @@ "frontEndScaleFactor": "[parameters('frontEndScaleFactor')]", "internalLoadBalancingMode": "[parameters('internalLoadBalancingMode')]", "upgradePreference": "[parameters('upgradePreference')]", + "networkingConfiguration": "[parameters('networkConfiguration')]", "virtualNetwork": { "id": "[parameters('subnetResourceId')]", "subnet": "[last(split(parameters('subnetResourceId'), '/'))]" @@ -503,137 +497,20 @@ "appServiceEnvironment_roleAssignments": { "copy": { "name": "appServiceEnvironment_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Web/hostingEnvironments/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Web/hostingEnvironments', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", - "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" - }, - "dependsOn": [ - "appServiceEnvironment" - ] - }, - "appServiceEnvironment_configurations_networking": { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-AppServiceEnv-Configurations-Networking', uniqueString(deployment().name, parameters('location')))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Web/hostingEnvironments', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "hostingEnvironmentName": { - "value": "[parameters('name')]" - }, - "allowNewPrivateEndpointConnections": { - "value": "[parameters('allowNewPrivateEndpointConnections')]" - }, - "ftpEnabled": { - "value": "[parameters('ftpEnabled')]" - }, - "inboundIpAddressOverride": { - "value": "[parameters('inboundIpAddressOverride')]" - }, - "remoteDebugEnabled": { - "value": "[parameters('remoteDebugEnabled')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "17598276744130339630" - }, - "name": "Hosting Environment Network Configuration", - "description": "This module deploys a Hosting Environment Network Configuration.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "hostingEnvironmentName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent Hosting Environment. Required if the template is used in a standalone deployment." - } - }, - "allowNewPrivateEndpointConnections": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Property to enable and disable new private endpoint connection creation on ASE." - } - }, - "ftpEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Property to enable and disable FTP on ASEV3." - } - }, - "inboundIpAddressOverride": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Customer provided Inbound IP Address. Only able to be set on Ase create." - } - }, - "remoteDebugEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Property to enable and disable Remote Debug on ASEv3." - } - } - }, - "resources": [ - { - "type": "Microsoft.Web/hostingEnvironments/configurations", - "apiVersion": "2022-03-01", - "name": "[format('{0}/{1}', parameters('hostingEnvironmentName'), 'networking')]", - "properties": { - "allowNewPrivateEndpointConnections": "[parameters('allowNewPrivateEndpointConnections')]", - "ftpEnabled": "[parameters('ftpEnabled')]", - "inboundIpAddressOverride": "[parameters('inboundIpAddressOverride')]", - "remoteDebugEnabled": "[parameters('remoteDebugEnabled')]" - } - } - ], - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the configuration." - }, - "value": "networking" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the deployed configuration." - }, - "value": "[resourceId('Microsoft.Web/hostingEnvironments/configurations', parameters('hostingEnvironmentName'), 'networking')]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The resource group of the deployed configuration." - }, - "value": "[resourceGroup().name]" - } - } - } + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "appServiceEnvironment" @@ -669,8 +546,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "12791869385776671140" + "version": "0.30.3.12046", + "templateHash": "8555887239478847203" }, "name": "Hosting Environment Custom DNS Suffix Configuration", "description": "This module deploys a Hosting Environment Custom DNS Suffix Configuration.", @@ -705,7 +582,7 @@ "resources": [ { "type": "Microsoft.Web/hostingEnvironments/configurations", - "apiVersion": "2022-03-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('hostingEnvironmentName'), 'customdnssuffix')]", "properties": { "certificateUrl": "[parameters('certificateUrl')]", @@ -771,14 +648,14 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('appServiceEnvironment', '2022-03-01', 'full').location]" + "value": "[reference('appServiceEnvironment', '2023-12-01', 'full').location]" }, "systemAssignedMIPrincipalId": { "type": "string", "metadata": { "description": "The principal ID of the system assigned identity." }, - "value": "[coalesce(tryGet(tryGet(reference('appServiceEnvironment', '2022-03-01', 'full'), 'identity'), 'principalId'), '')]" + "value": "[coalesce(tryGet(tryGet(reference('appServiceEnvironment', '2023-12-01', 'full'), 'identity'), 'principalId'), '')]" } } } \ No newline at end of file diff --git a/avm/res/web/hosting-environment/tests/e2e/defaults/main.test.bicep b/avm/res/web/hosting-environment/tests/e2e/defaults/main.test.bicep index 185e2660d2..e97449aecc 100644 --- a/avm/res/web/hosting-environment/tests/e2e/defaults/main.test.bicep +++ b/avm/res/web/hosting-environment/tests/e2e/defaults/main.test.bicep @@ -54,7 +54,6 @@ module testDeployment '../../../main.bicep' = [ // You parameters go here name: '${namePrefix}${serviceShort}001' location: resourceLocation - kind: 'ASEv3' subnetResourceId: nestedDependencies.outputs.subnetResourceId } } diff --git a/avm/res/web/hosting-environment/tests/e2e/max/main.test.bicep b/avm/res/web/hosting-environment/tests/e2e/max/main.test.bicep index 47479ecf26..b993ec1f83 100644 --- a/avm/res/web/hosting-environment/tests/e2e/max/main.test.bicep +++ b/avm/res/web/hosting-environment/tests/e2e/max/main.test.bicep @@ -68,6 +68,7 @@ module testDeployment '../../../main.bicep' = [ params: { name: '${namePrefix}${serviceShort}001' location: resourceGroup.location + kind: 'ASEv3' tags: { 'hidden-title': 'This is visible in the resource name' resourceType: 'App Service Environment' @@ -79,11 +80,13 @@ module testDeployment '../../../main.bicep' = [ } roleAssignments: [ { + name: '97fc1da9-bfe4-409d-b17a-da9a82fad0d0' roleDefinitionIdOrName: 'Owner' principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } { + name: guid('Custom seed ${namePrefix}${serviceShort}') roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' @@ -99,16 +102,21 @@ module testDeployment '../../../main.bicep' = [ ] subnetResourceId: nestedDependencies.outputs.subnetResourceId internalLoadBalancingMode: 'Web, Publishing' + networkConfiguration: { + properties: { + allowNewPrivateEndpointConnections: true + ftpEnabled: true + inboundIpAddressOverride: '10.0.0.10' + remoteDebugEnabled: true + } + } clusterSettings: [ { name: 'DisableTls1.0' value: '1' } ] - allowNewPrivateEndpointConnections: true - ftpEnabled: true - inboundIpAddressOverride: '10.0.0.10' - remoteDebugEnabled: true + zoneRedundant: true upgradePreference: 'Late' diagnosticSettings: [ { diff --git a/avm/res/web/hosting-environment/tests/e2e/waf-aligned/main.test.bicep b/avm/res/web/hosting-environment/tests/e2e/waf-aligned/main.test.bicep index 9485e23be4..00ef06ab2f 100644 --- a/avm/res/web/hosting-environment/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/web/hosting-environment/tests/e2e/waf-aligned/main.test.bicep @@ -81,10 +81,13 @@ module testDeployment '../../../main.bicep' = [ value: '1' } ] - allowNewPrivateEndpointConnections: true - ftpEnabled: true - inboundIpAddressOverride: '10.0.0.10' - remoteDebugEnabled: true + networkConfiguration: { + properties: { + allowNewPrivateEndpointConnections: true + ftpEnabled: true + remoteDebugEnabled: true + } + } upgradePreference: 'Late' diagnosticSettings: [ { diff --git a/avm/res/web/hosting-environment/version.json b/avm/res/web/hosting-environment/version.json index 8def869ede..daf1a794d9 100644 --- a/avm/res/web/hosting-environment/version.json +++ b/avm/res/web/hosting-environment/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.2", "pathFilters": [ "./main.json" ] diff --git a/avm/res/web/site/README.md b/avm/res/web/site/README.md index 449f709e49..7e1a4a2b04 100644 --- a/avm/res/web/site/README.md +++ b/avm/res/web/site/README.md @@ -21,16 +21,16 @@ This module deploys a Web or Function App. | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | | `Microsoft.Network/privateEndpoints` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints) | | `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints/privateDnsZoneGroups) | -| `Microsoft.Web/sites` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | -| `Microsoft.Web/sites/basicPublishingCredentialsPolicies` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | -| `Microsoft.Web/sites/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | -| `Microsoft.Web/sites/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | -| `Microsoft.Web/sites/extensions` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites/extensions) | -| `Microsoft.Web/sites/hybridConnectionNamespaces/relays` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-09-01/sites/hybridConnectionNamespaces/relays) | -| `Microsoft.Web/sites/slots` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites/slots) | -| `Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | -| `Microsoft.Web/sites/slots/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | -| `Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-09-01/sites/slots/hybridConnectionNamespaces/relays) | +| `Microsoft.Web/sites` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites) | +| `Microsoft.Web/sites/basicPublishingCredentialsPolicies` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/basicPublishingCredentialsPolicies) | +| `Microsoft.Web/sites/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/config) | +| `Microsoft.Web/sites/extensions` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/extensions) | +| `Microsoft.Web/sites/hybridConnectionNamespaces/relays` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/hybridConnectionNamespaces/relays) | +| `Microsoft.Web/sites/slots` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots) | +| `Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots/basicPublishingCredentialsPolicies) | +| `Microsoft.Web/sites/slots/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-09-01/sites/slots/config) | +| `Microsoft.Web/sites/slots/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots/config) | +| `Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots/hybridConnectionNamespaces/relays) | ## Usage examples @@ -3054,7 +3054,7 @@ param siteConfig = { | [`redundancyMode`](#parameter-redundancymode) | string | Site redundancy mode. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | | [`scmSiteAlsoStopped`](#parameter-scmsitealsostopped) | bool | Stop SCM (KUDU) site when the app is stopped. | -| [`siteConfig`](#parameter-siteconfig) | object | The site config object. | +| [`siteConfig`](#parameter-siteconfig) | object | The site config object. The defaults are set to the following values: alwaysOn: true, minTlsVersion: '1.2', ftpsState: 'FtpsOnly'. | | [`slots`](#parameter-slots) | array | Configuration for deployment slots for an app. | | [`storageAccountRequired`](#parameter-storageaccountrequired) | bool | Checks if Customer provided storage account is required. | | [`storageAccountResourceId`](#parameter-storageaccountresourceid) | string | Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions. | @@ -3563,15 +3563,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -3580,6 +3578,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. @@ -4047,7 +4052,7 @@ Stop SCM (KUDU) site when the app is stopped. ### Parameter: `siteConfig` -The site config object. +The site config object. The defaults are set to the following values: alwaysOn: true, minTlsVersion: '1.2', ftpsState: 'FtpsOnly'. - Required: No - Type: object @@ -4055,6 +4060,8 @@ The site config object. ```Bicep { alwaysOn: true + ftpsState: 'FtpsOnly' + minTlsVersion: '1.2' } ``` diff --git a/avm/res/web/site/basic-publishing-credentials-policy/README.md b/avm/res/web/site/basic-publishing-credentials-policy/README.md index 83d183469b..e5324dbcb1 100644 --- a/avm/res/web/site/basic-publishing-credentials-policy/README.md +++ b/avm/res/web/site/basic-publishing-credentials-policy/README.md @@ -12,7 +12,7 @@ This module deploys a Web Site Basic Publishing Credentials Policy. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/basicPublishingCredentialsPolicies` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | +| `Microsoft.Web/sites/basicPublishingCredentialsPolicies` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/basicPublishingCredentialsPolicies) | ## Parameters diff --git a/avm/res/web/site/basic-publishing-credentials-policy/main.bicep b/avm/res/web/site/basic-publishing-credentials-policy/main.bicep index f09d81edf7..5006e2068f 100644 --- a/avm/res/web/site/basic-publishing-credentials-policy/main.bicep +++ b/avm/res/web/site/basic-publishing-credentials-policy/main.bicep @@ -18,11 +18,11 @@ param webAppName string @description('Optional. Location for all Resources.') param location string = resourceGroup().location -resource webApp 'Microsoft.Web/sites@2022-09-01' existing = { +resource webApp 'Microsoft.Web/sites@2023-12-01' existing = { name: webAppName } -resource basicPublishingCredentialsPolicy 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2022-09-01' = { +resource basicPublishingCredentialsPolicy 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2023-12-01' = { #disable-next-line BCP225 // False-positive. Value is required. name: name location: location diff --git a/avm/res/web/site/basic-publishing-credentials-policy/main.json b/avm/res/web/site/basic-publishing-credentials-policy/main.json index 2f34f50dae..2d779d2d14 100644 --- a/avm/res/web/site/basic-publishing-credentials-policy/main.json +++ b/avm/res/web/site/basic-publishing-credentials-policy/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "2961784489694025029" + "templateHash": "15847824660831257384" }, "name": "Web Site Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Basic Publishing Credentials Policy.", @@ -46,7 +46,7 @@ "resources": [ { "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('webAppName'), parameters('name'))]", "location": "[parameters('location')]", "properties": { @@ -81,7 +81,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.Web/sites/basicPublishingCredentialsPolicies', parameters('webAppName'), parameters('name')), '2022-09-01', 'full').location]" + "value": "[reference(resourceId('Microsoft.Web/sites/basicPublishingCredentialsPolicies', parameters('webAppName'), parameters('name')), '2023-12-01', 'full').location]" } } } \ No newline at end of file diff --git a/avm/res/web/site/config--appsettings/README.md b/avm/res/web/site/config--appsettings/README.md index db4a05b7d7..534da22e89 100644 --- a/avm/res/web/site/config--appsettings/README.md +++ b/avm/res/web/site/config--appsettings/README.md @@ -13,7 +13,7 @@ This module deploys a Site App Setting. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | +| `Microsoft.Web/sites/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/config) | ## Parameters diff --git a/avm/res/web/site/config--authsettingsv2/README.md b/avm/res/web/site/config--authsettingsv2/README.md index b36b277e22..2e46d48d19 100644 --- a/avm/res/web/site/config--authsettingsv2/README.md +++ b/avm/res/web/site/config--authsettingsv2/README.md @@ -12,7 +12,7 @@ This module deploys a Site Auth Settings V2 Configuration. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | +| `Microsoft.Web/sites/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/config) | ## Parameters diff --git a/avm/res/web/site/config--authsettingsv2/main.bicep b/avm/res/web/site/config--authsettingsv2/main.bicep index d5e2466c41..ba5a323043 100644 --- a/avm/res/web/site/config--authsettingsv2/main.bicep +++ b/avm/res/web/site/config--authsettingsv2/main.bicep @@ -25,11 +25,11 @@ param kind string @description('Required. The auth settings V2 configuration.') param authSettingV2Configuration object -resource app 'Microsoft.Web/sites@2022-09-01' existing = { +resource app 'Microsoft.Web/sites@2023-12-01' existing = { name: appName } -resource appSettings 'Microsoft.Web/sites/config@2022-09-01' = { +resource appSettings 'Microsoft.Web/sites/config@2023-12-01' = { name: 'authsettingsV2' kind: kind parent: app diff --git a/avm/res/web/site/config--authsettingsv2/main.json b/avm/res/web/site/config--authsettingsv2/main.json index 40a2f7b4a3..34f9f10696 100644 --- a/avm/res/web/site/config--authsettingsv2/main.json +++ b/avm/res/web/site/config--authsettingsv2/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "9901606105705730734" + "templateHash": "7782125422759995841" }, "name": "Site Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -48,7 +48,7 @@ "resources": [ { "type": "Microsoft.Web/sites/config", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('appName'), 'authsettingsV2')]", "kind": "[parameters('kind')]", "properties": "[parameters('authSettingV2Configuration')]" diff --git a/avm/res/web/site/config--logs/README.md b/avm/res/web/site/config--logs/README.md index 3bb077af5d..32a5167e71 100644 --- a/avm/res/web/site/config--logs/README.md +++ b/avm/res/web/site/config--logs/README.md @@ -12,7 +12,7 @@ This module deploys a Site logs Configuration. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | +| `Microsoft.Web/sites/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/config) | ## Parameters @@ -21,6 +21,11 @@ This module deploys a Site logs Configuration. | Parameter | Type | Description | | :-- | :-- | :-- | | [`appName`](#parameter-appname) | string | The name of the parent site resource. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | | [`logsConfiguration`](#parameter-logsconfiguration) | object | The logs settings configuration. | ### Parameter: `appName` diff --git a/avm/res/web/site/config--logs/main.bicep b/avm/res/web/site/config--logs/main.bicep index 3f83ed600f..7b8da4ca0f 100644 --- a/avm/res/web/site/config--logs/main.bicep +++ b/avm/res/web/site/config--logs/main.bicep @@ -5,14 +5,14 @@ metadata owner = 'Azure/module-maintainers' @description('Required. The name of the parent site resource.') param appName string -@description('Required. The logs settings configuration.') +@description('Optional. The logs settings configuration.') param logsConfiguration object? -resource app 'Microsoft.Web/sites@2022-09-01' existing = { +resource app 'Microsoft.Web/sites@2023-12-01' existing = { name: appName } -resource webSettings 'Microsoft.Web/sites/config@2022-09-01' = { +resource webSettings 'Microsoft.Web/sites/config@2023-12-01' = { name: 'logs' kind: 'string' parent: app diff --git a/avm/res/web/site/config--logs/main.json b/avm/res/web/site/config--logs/main.json index df3ade39ea..b22108e5fe 100644 --- a/avm/res/web/site/config--logs/main.json +++ b/avm/res/web/site/config--logs/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "5314244939846396394" + "templateHash": "2527104715221107836" }, "name": "Site logs Config", "description": "This module deploys a Site logs Configuration.", @@ -23,7 +23,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Required. The logs settings configuration." + "description": "Optional. The logs settings configuration." } } }, @@ -31,12 +31,12 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "webSettings": { "type": "Microsoft.Web/sites/config", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('appName'), 'logs')]", "kind": "string", "properties": "[parameters('logsConfiguration')]", diff --git a/avm/res/web/site/config--web/README.md b/avm/res/web/site/config--web/README.md index ec967c3e6b..3b3cf09561 100644 --- a/avm/res/web/site/config--web/README.md +++ b/avm/res/web/site/config--web/README.md @@ -12,7 +12,7 @@ This module deploys a Site Api Management Configuration. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | +| `Microsoft.Web/sites/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/config) | ## Parameters @@ -20,15 +20,13 @@ This module deploys a Site Api Management Configuration. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`apiManagementConfiguration`](#parameter-apimanagementconfiguration) | object | The web settings api management configuration. | | [`appName`](#parameter-appname) | string | The name of the parent site resource. | -### Parameter: `apiManagementConfiguration` - -The web settings api management configuration. +**Optional parameters** -- Required: No -- Type: object +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`apiManagementConfiguration`](#parameter-apimanagementconfiguration) | object | The web settings api management configuration. | ### Parameter: `appName` @@ -37,6 +35,13 @@ The name of the parent site resource. - Required: Yes - Type: string +### Parameter: `apiManagementConfiguration` + +The web settings api management configuration. + +- Required: No +- Type: object + ## Outputs | Output | Type | Description | diff --git a/avm/res/web/site/config--web/main.bicep b/avm/res/web/site/config--web/main.bicep index 61000e6ed8..6380556789 100644 --- a/avm/res/web/site/config--web/main.bicep +++ b/avm/res/web/site/config--web/main.bicep @@ -5,14 +5,14 @@ metadata owner = 'Azure/module-maintainers' @description('Required. The name of the parent site resource.') param appName string -@description('Required. The web settings api management configuration.') +@description('Optional. The web settings api management configuration.') param apiManagementConfiguration object? -resource app 'Microsoft.Web/sites@2022-09-01' existing = { +resource app 'Microsoft.Web/sites@2023-12-01' existing = { name: appName } -resource webSettings 'Microsoft.Web/sites/config@2022-09-01' = { +resource webSettings 'Microsoft.Web/sites/config@2023-12-01' = { name: 'web' kind: 'string' parent: app diff --git a/avm/res/web/site/config--web/main.json b/avm/res/web/site/config--web/main.json index 7e101b4952..75a81a9720 100644 --- a/avm/res/web/site/config--web/main.json +++ b/avm/res/web/site/config--web/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "4796843420829841335" + "templateHash": "18186736059685095806" }, "name": "Site Api Management Config", "description": "This module deploys a Site Api Management Configuration.", @@ -23,7 +23,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Required. The web settings api management configuration." + "description": "Optional. The web settings api management configuration." } } }, @@ -31,12 +31,12 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "webSettings": { "type": "Microsoft.Web/sites/config", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('appName'), 'web')]", "kind": "string", "properties": "[parameters('apiManagementConfiguration')]", diff --git a/avm/res/web/site/extensions--msdeploy/README.md b/avm/res/web/site/extensions--msdeploy/README.md index 0def3b7ba3..6b5415e2ac 100644 --- a/avm/res/web/site/extensions--msdeploy/README.md +++ b/avm/res/web/site/extensions--msdeploy/README.md @@ -12,7 +12,7 @@ This module deploys a Site extension for MSDeploy. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/extensions` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites/extensions) | +| `Microsoft.Web/sites/extensions` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/extensions) | ## Parameters @@ -21,6 +21,11 @@ This module deploys a Site extension for MSDeploy. | Parameter | Type | Description | | :-- | :-- | :-- | | [`appName`](#parameter-appname) | string | The name of the parent site resource. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | | [`msDeployConfiguration`](#parameter-msdeployconfiguration) | object | Sets the MSDeployment Properties. | ### Parameter: `appName` diff --git a/avm/res/web/site/extensions--msdeploy/main.bicep b/avm/res/web/site/extensions--msdeploy/main.bicep index 07d8ef3405..bf4220cf51 100644 --- a/avm/res/web/site/extensions--msdeploy/main.bicep +++ b/avm/res/web/site/extensions--msdeploy/main.bicep @@ -5,10 +5,10 @@ metadata owner = 'Azure/module-maintainers' @description('Required. The name of the parent site resource.') param appName string -@description('Required. Sets the MSDeployment Properties.') +@description('Optional. Sets the MSDeployment Properties.') param msDeployConfiguration object? -resource app 'Microsoft.Web/sites@2022-09-01' existing = { +resource app 'Microsoft.Web/sites@2023-12-01' existing = { name: appName } resource msdeploy 'Microsoft.Web/sites/extensions@2023-12-01' = { diff --git a/avm/res/web/site/extensions--msdeploy/main.json b/avm/res/web/site/extensions--msdeploy/main.json index 79be0b21b8..069239c100 100644 --- a/avm/res/web/site/extensions--msdeploy/main.json +++ b/avm/res/web/site/extensions--msdeploy/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "8769701913978391000" + "templateHash": "10249716032875912201" }, "name": "Site Deployment Extension ", "description": "This module deploys a Site extension for MSDeploy.", @@ -23,7 +23,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Required. Sets the MSDeployment Properties." + "description": "Optional. Sets the MSDeployment Properties." } } }, @@ -31,7 +31,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "msdeploy": { diff --git a/avm/res/web/site/hybrid-connection-namespace/relay/README.md b/avm/res/web/site/hybrid-connection-namespace/relay/README.md index 47501d1cac..eb49bee22e 100644 --- a/avm/res/web/site/hybrid-connection-namespace/relay/README.md +++ b/avm/res/web/site/hybrid-connection-namespace/relay/README.md @@ -12,7 +12,7 @@ This module deploys a Site Hybrid Connection Namespace Relay. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/hybridConnectionNamespaces/relays` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-09-01/sites/hybridConnectionNamespaces/relays) | +| `Microsoft.Web/sites/hybridConnectionNamespaces/relays` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/hybridConnectionNamespaces/relays) | ## Parameters diff --git a/avm/res/web/site/hybrid-connection-namespace/relay/main.bicep b/avm/res/web/site/hybrid-connection-namespace/relay/main.bicep index 7b64d67dc9..cb79f954bb 100644 --- a/avm/res/web/site/hybrid-connection-namespace/relay/main.bicep +++ b/avm/res/web/site/hybrid-connection-namespace/relay/main.bicep @@ -24,7 +24,7 @@ resource namespace 'Microsoft.Relay/namespaces@2021-11-01' existing = { } } -resource hybridConnectionRelay 'Microsoft.Web/sites/hybridConnectionNamespaces/relays@2022-09-01' = { +resource hybridConnectionRelay 'Microsoft.Web/sites/hybridConnectionNamespaces/relays@2023-12-01' = { name: '${appName}/${namespace.name}/${namespace::hybridConnection.name}' properties: { serviceBusNamespace: namespace.name diff --git a/avm/res/web/site/hybrid-connection-namespace/relay/main.json b/avm/res/web/site/hybrid-connection-namespace/relay/main.json index 6f55127261..bac0f9d832 100644 --- a/avm/res/web/site/hybrid-connection-namespace/relay/main.json +++ b/avm/res/web/site/hybrid-connection-namespace/relay/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "1833159536134902561" + "templateHash": "9545759447796150909" }, "name": "Web/Function Apps Hybrid Connection Relay", "description": "This module deploys a Site Hybrid Connection Namespace Relay.", @@ -35,7 +35,7 @@ "resources": [ { "type": "Microsoft.Web/sites/hybridConnectionNamespaces/relays", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]", "properties": { "serviceBusNamespace": "[split(parameters('hybridConnectionResourceId'), '/')[8]]", diff --git a/avm/res/web/site/main.bicep b/avm/res/web/site/main.bicep index 369399a325..01a9f7a228 100644 --- a/avm/res/web/site/main.bicep +++ b/avm/res/web/site/main.bicep @@ -64,9 +64,11 @@ param vnetRouteAllEnabled bool = false @description('Optional. Stop SCM (KUDU) site when the app is stopped.') param scmSiteAlsoStopped bool = false -@description('Optional. The site config object.') +@description('Optional. The site config object. The defaults are set to the following values: alwaysOn: true, minTlsVersion: \'1.2\', ftpsState: \'FtpsOnly\'.') param siteConfig object = { alwaysOn: true + minTlsVersion: '1.2' + ftpsState: 'FtpsOnly' } @description('Optional. The Function App configuration object.') @@ -655,7 +657,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/web/site/main.json b/avm/res/web/site/main.json index ad24381ffc..3df6f5d784 100644 --- a/avm/res/web/site/main.json +++ b/avm/res/web/site/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "12115053115954215642" + "templateHash": "15895523310817597793" }, "name": "Web/Function Apps", "description": "This module deploys a Web or Function App.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -601,10 +601,12 @@ "siteConfig": { "type": "object", "defaultValue": { - "alwaysOn": true + "alwaysOn": true, + "minTlsVersion": "1.2", + "ftpsState": "FtpsOnly" }, "metadata": { - "description": "Optional. The site config object." + "description": "Optional. The site config object. The defaults are set to the following values: alwaysOn: true, minTlsVersion: '1.2', ftpsState: 'FtpsOnly'." } }, "functionAppConfig": { @@ -1181,7 +1183,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "9901606105705730734" + "templateHash": "7782125422759995841" }, "name": "Site Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -1224,7 +1226,7 @@ "resources": [ { "type": "Microsoft.Web/sites/config", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('appName'), 'authsettingsV2')]", "kind": "[parameters('kind')]", "properties": "[parameters('authSettingV2Configuration')]" @@ -1285,7 +1287,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "5314244939846396394" + "templateHash": "2527104715221107836" }, "name": "Site logs Config", "description": "This module deploys a Site logs Configuration.", @@ -1302,7 +1304,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Required. The logs settings configuration." + "description": "Optional. The logs settings configuration." } } }, @@ -1310,12 +1312,12 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "webSettings": { "type": "Microsoft.Web/sites/config", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('appName'), 'logs')]", "kind": "string", "properties": "[parameters('logsConfiguration')]", @@ -1380,7 +1382,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "4796843420829841335" + "templateHash": "18186736059685095806" }, "name": "Site Api Management Config", "description": "This module deploys a Site Api Management Configuration.", @@ -1397,7 +1399,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Required. The web settings api management configuration." + "description": "Optional. The web settings api management configuration." } } }, @@ -1405,12 +1407,12 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "webSettings": { "type": "Microsoft.Web/sites/config", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('appName'), 'web')]", "kind": "string", "properties": "[parameters('apiManagementConfiguration')]", @@ -1474,7 +1476,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "8769701913978391000" + "templateHash": "10249716032875912201" }, "name": "Site Deployment Extension ", "description": "This module deploys a Site extension for MSDeploy.", @@ -1491,7 +1493,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Required. Sets the MSDeployment Properties." + "description": "Optional. Sets the MSDeployment Properties." } } }, @@ -1499,7 +1501,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "msdeploy": { @@ -1696,7 +1698,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "16398712095816733590" + "templateHash": "2418467213841620758" }, "name": "Web/Function App Deployment Slots", "description": "This module deploys a Web or Function App Deployment Slot.", @@ -1927,7 +1929,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -2517,7 +2519,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2021-03-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "slot": { @@ -2677,7 +2679,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "4751023237415156564" + "templateHash": "3011151783207983935" }, "name": "Site Slot App Settings", "description": "This module deploys a Site Slot App Setting.", @@ -2756,7 +2758,7 @@ "app::slot": { "existing": true, "type": "Microsoft.Web/sites/slots", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('appName'), parameters('slotName'))]", "dependsOn": [ "app" @@ -2765,7 +2767,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "appInsight": { @@ -2781,7 +2783,7 @@ "condition": "[not(empty(parameters('storageAccountResourceId')))]", "existing": true, "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2023-01-01", + "apiVersion": "2023-05-01", "subscriptionId": "[split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2]]", "resourceGroup": "[split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]]", "name": "[last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))]" @@ -2791,7 +2793,7 @@ "apiVersion": "2022-09-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), 'appsettings')]", "kind": "[parameters('kind')]", - "properties": "[union(coalesce(parameters('currentAppSettings'), createObject()), coalesce(parameters('appSettingsKeyValuePairs'), createObject()), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/')), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), '2023-01-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), union(createObject('AzureWebJobsStorage__accountName', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), createObject('AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob)), createObject())), if(not(empty(parameters('appInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('appInsight').ConnectionString), createObject()))]", + "properties": "[union(coalesce(parameters('currentAppSettings'), createObject()), coalesce(parameters('appSettingsKeyValuePairs'), createObject()), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/')), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), '2023-05-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), union(createObject('AzureWebJobsStorage__accountName', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), createObject('AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob)), createObject())), if(not(empty(parameters('appInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('appInsight').ConnectionString), createObject()))]", "dependsOn": [ "appInsight", "app::slot", @@ -2860,7 +2862,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "12145671704242923554" + "templateHash": "7842363652527859767" }, "name": "Site Slot Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -2909,7 +2911,7 @@ "resources": [ { "type": "Microsoft.Web/sites/slots/config", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), 'authsettingsV2')]", "kind": "[parameters('kind')]", "properties": "[parameters('authSettingV2Configuration')]" @@ -2982,7 +2984,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "9837227282603977030" + "templateHash": "1564349757337430633" }, "name": "Web Site Slot Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Slot Basic Publishing Credentials Policy.", @@ -3029,7 +3031,7 @@ "resources": [ { "type": "Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), parameters('name'))]", "location": "[parameters('location')]", "properties": { @@ -3064,7 +3066,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies', parameters('appName'), parameters('slotName'), parameters('name')), '2022-09-01', 'full').location]" + "value": "[reference(resourceId('Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies', parameters('appName'), parameters('slotName'), parameters('name')), '2023-12-01', 'full').location]" } } } @@ -3108,7 +3110,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "1330320751784094185" + "templateHash": "12569198723769767672" }, "name": "Web/Function Apps Slot Hybrid Connection Relay", "description": "This module deploys a Site Slot Hybrid Connection Namespace Relay.", @@ -3144,7 +3146,7 @@ "resources": [ { "type": "Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}/{3}', parameters('appName'), parameters('slotName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]", "properties": { "serviceBusNamespace": "[split(parameters('hybridConnectionResourceId'), '/')[8]]", @@ -3214,7 +3216,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "8769701913978391000" + "templateHash": "10249716032875912201" }, "name": "Site Deployment Extension ", "description": "This module deploys a Site extension for MSDeploy.", @@ -3231,7 +3233,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Required. Sets the MSDeployment Properties." + "description": "Optional. Sets the MSDeployment Properties." } } }, @@ -3239,7 +3241,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "msdeploy": { @@ -4143,7 +4145,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "2961784489694025029" + "templateHash": "15847824660831257384" }, "name": "Web Site Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Basic Publishing Credentials Policy.", @@ -4184,7 +4186,7 @@ "resources": [ { "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('webAppName'), parameters('name'))]", "location": "[parameters('location')]", "properties": { @@ -4219,7 +4221,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.Web/sites/basicPublishingCredentialsPolicies', parameters('webAppName'), parameters('name')), '2022-09-01', 'full').location]" + "value": "[reference(resourceId('Microsoft.Web/sites/basicPublishingCredentialsPolicies', parameters('webAppName'), parameters('name')), '2023-12-01', 'full').location]" } } } @@ -4259,7 +4261,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "1833159536134902561" + "templateHash": "9545759447796150909" }, "name": "Web/Function Apps Hybrid Connection Relay", "description": "This module deploys a Site Hybrid Connection Namespace Relay.", @@ -4289,7 +4291,7 @@ "resources": [ { "type": "Microsoft.Web/sites/hybridConnectionNamespaces/relays", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]", "properties": { "serviceBusNamespace": "[split(parameters('hybridConnectionResourceId'), '/')[8]]", diff --git a/avm/res/web/site/slot/README.md b/avm/res/web/site/slot/README.md index 60d39f4ef0..e34643c5e3 100644 --- a/avm/res/web/site/slot/README.md +++ b/avm/res/web/site/slot/README.md @@ -20,11 +20,12 @@ This module deploys a Web or Function App Deployment Slot. | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | | `Microsoft.Network/privateEndpoints` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints) | | `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints/privateDnsZoneGroups) | -| `Microsoft.Web/sites/extensions` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites/extensions) | -| `Microsoft.Web/sites/slots` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites/slots) | -| `Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | -| `Microsoft.Web/sites/slots/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | -| `Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-09-01/sites/slots/hybridConnectionNamespaces/relays) | +| `Microsoft.Web/sites/extensions` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/extensions) | +| `Microsoft.Web/sites/slots` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots) | +| `Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots/basicPublishingCredentialsPolicies) | +| `Microsoft.Web/sites/slots/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-09-01/sites/slots/config) | +| `Microsoft.Web/sites/slots/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots/config) | +| `Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots/hybridConnectionNamespaces/relays) | ## Parameters @@ -570,15 +571,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -587,6 +586,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/web/site/slot/basic-publishing-credentials-policy/README.md b/avm/res/web/site/slot/basic-publishing-credentials-policy/README.md index 4809f839c2..578bda4353 100644 --- a/avm/res/web/site/slot/basic-publishing-credentials-policy/README.md +++ b/avm/res/web/site/slot/basic-publishing-credentials-policy/README.md @@ -12,7 +12,7 @@ This module deploys a Web Site Slot Basic Publishing Credentials Policy. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | +| `Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots/basicPublishingCredentialsPolicies) | ## Parameters diff --git a/avm/res/web/site/slot/basic-publishing-credentials-policy/main.bicep b/avm/res/web/site/slot/basic-publishing-credentials-policy/main.bicep index 327b4566cd..249a1b899f 100644 --- a/avm/res/web/site/slot/basic-publishing-credentials-policy/main.bicep +++ b/avm/res/web/site/slot/basic-publishing-credentials-policy/main.bicep @@ -21,7 +21,7 @@ param slotName string @description('Optional. Location for all Resources.') param location string = resourceGroup().location -resource app 'Microsoft.Web/sites@2022-09-01' existing = { +resource app 'Microsoft.Web/sites@2023-12-01' existing = { name: appName resource slot 'slots' existing = { @@ -29,7 +29,7 @@ resource app 'Microsoft.Web/sites@2022-09-01' existing = { } } -resource basicPublishingCredentialsPolicy 'Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies@2022-09-01' = { +resource basicPublishingCredentialsPolicy 'Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies@2023-12-01' = { #disable-next-line BCP225 // False-positive. Value is required. name: name location: location diff --git a/avm/res/web/site/slot/basic-publishing-credentials-policy/main.json b/avm/res/web/site/slot/basic-publishing-credentials-policy/main.json index f5534dba2f..d18f65520b 100644 --- a/avm/res/web/site/slot/basic-publishing-credentials-policy/main.json +++ b/avm/res/web/site/slot/basic-publishing-credentials-policy/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "9837227282603977030" + "templateHash": "1564349757337430633" }, "name": "Web Site Slot Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Slot Basic Publishing Credentials Policy.", @@ -52,7 +52,7 @@ "resources": [ { "type": "Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), parameters('name'))]", "location": "[parameters('location')]", "properties": { @@ -87,7 +87,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies', parameters('appName'), parameters('slotName'), parameters('name')), '2022-09-01', 'full').location]" + "value": "[reference(resourceId('Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies', parameters('appName'), parameters('slotName'), parameters('name')), '2023-12-01', 'full').location]" } } } \ No newline at end of file diff --git a/avm/res/web/site/slot/config--appsettings/README.md b/avm/res/web/site/slot/config--appsettings/README.md index a4eaf7b5e3..2bca1e1517 100644 --- a/avm/res/web/site/slot/config--appsettings/README.md +++ b/avm/res/web/site/slot/config--appsettings/README.md @@ -13,7 +13,7 @@ This module deploys a Site Slot App Setting. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/slots/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | +| `Microsoft.Web/sites/slots/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-09-01/sites/slots/config) | ## Parameters diff --git a/avm/res/web/site/slot/config--appsettings/main.bicep b/avm/res/web/site/slot/config--appsettings/main.bicep index 2fbe7b81d4..d9e873d820 100644 --- a/avm/res/web/site/slot/config--appsettings/main.bicep +++ b/avm/res/web/site/slot/config--appsettings/main.bicep @@ -64,7 +64,7 @@ var expandedAppSettings = union( appInsightsValues ) -resource app 'Microsoft.Web/sites@2022-09-01' existing = { +resource app 'Microsoft.Web/sites@2023-12-01' existing = { name: appName resource slot 'slots' existing = { @@ -77,7 +77,7 @@ resource appInsight 'Microsoft.Insights/components@2020-02-02' existing = if (!e scope: resourceGroup(split(appInsightResourceId ?? '//', '/')[2], split(appInsightResourceId ?? '////', '/')[4]) } -resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = if (!empty(storageAccountResourceId)) { +resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing = if (!empty(storageAccountResourceId)) { name: last(split(storageAccountResourceId ?? 'dummyName', '/'))! scope: resourceGroup( split(storageAccountResourceId ?? '//', '/')[2], diff --git a/avm/res/web/site/slot/config--appsettings/main.json b/avm/res/web/site/slot/config--appsettings/main.json index db3ee7ad32..e3b453acd4 100644 --- a/avm/res/web/site/slot/config--appsettings/main.json +++ b/avm/res/web/site/slot/config--appsettings/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "4751023237415156564" + "templateHash": "3011151783207983935" }, "name": "Site Slot App Settings", "description": "This module deploys a Site Slot App Setting.", @@ -85,7 +85,7 @@ "app::slot": { "existing": true, "type": "Microsoft.Web/sites/slots", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('appName'), parameters('slotName'))]", "dependsOn": [ "app" @@ -94,7 +94,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "appInsight": { @@ -110,7 +110,7 @@ "condition": "[not(empty(parameters('storageAccountResourceId')))]", "existing": true, "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2023-01-01", + "apiVersion": "2023-05-01", "subscriptionId": "[split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2]]", "resourceGroup": "[split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]]", "name": "[last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))]" @@ -120,7 +120,7 @@ "apiVersion": "2022-09-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), 'appsettings')]", "kind": "[parameters('kind')]", - "properties": "[union(coalesce(parameters('currentAppSettings'), createObject()), coalesce(parameters('appSettingsKeyValuePairs'), createObject()), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/')), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), '2023-01-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), union(createObject('AzureWebJobsStorage__accountName', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), createObject('AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob)), createObject())), if(not(empty(parameters('appInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('appInsight').ConnectionString), createObject()))]", + "properties": "[union(coalesce(parameters('currentAppSettings'), createObject()), coalesce(parameters('appSettingsKeyValuePairs'), createObject()), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/')), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), '2023-05-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), union(createObject('AzureWebJobsStorage__accountName', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), createObject('AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob)), createObject())), if(not(empty(parameters('appInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('appInsight').ConnectionString), createObject()))]", "dependsOn": [ "appInsight", "app::slot", diff --git a/avm/res/web/site/slot/config--authsettingsv2/README.md b/avm/res/web/site/slot/config--authsettingsv2/README.md index af8c04f6d3..8efa659e21 100644 --- a/avm/res/web/site/slot/config--authsettingsv2/README.md +++ b/avm/res/web/site/slot/config--authsettingsv2/README.md @@ -12,7 +12,7 @@ This module deploys a Site Auth Settings V2 Configuration. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/slots/config` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) | +| `Microsoft.Web/sites/slots/config` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots/config) | ## Parameters diff --git a/avm/res/web/site/slot/config--authsettingsv2/main.bicep b/avm/res/web/site/slot/config--authsettingsv2/main.bicep index 7b6b50f0a4..9471600088 100644 --- a/avm/res/web/site/slot/config--authsettingsv2/main.bicep +++ b/avm/res/web/site/slot/config--authsettingsv2/main.bicep @@ -28,7 +28,7 @@ param kind string @description('Required. The auth settings V2 configuration.') param authSettingV2Configuration object -resource app 'Microsoft.Web/sites@2022-09-01' existing = { +resource app 'Microsoft.Web/sites@2023-12-01' existing = { name: appName resource slot 'slots' existing = { @@ -36,7 +36,7 @@ resource app 'Microsoft.Web/sites@2022-09-01' existing = { } } -resource slotSettings 'Microsoft.Web/sites/slots/config@2022-09-01' = { +resource slotSettings 'Microsoft.Web/sites/slots/config@2023-12-01' = { name: 'authsettingsV2' kind: kind parent: app::slot diff --git a/avm/res/web/site/slot/config--authsettingsv2/main.json b/avm/res/web/site/slot/config--authsettingsv2/main.json index 65b5d4fa2b..c68af5ca88 100644 --- a/avm/res/web/site/slot/config--authsettingsv2/main.json +++ b/avm/res/web/site/slot/config--authsettingsv2/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "12145671704242923554" + "templateHash": "7842363652527859767" }, "name": "Site Slot Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -54,7 +54,7 @@ "resources": [ { "type": "Microsoft.Web/sites/slots/config", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), 'authsettingsV2')]", "kind": "[parameters('kind')]", "properties": "[parameters('authSettingV2Configuration')]" diff --git a/avm/res/web/site/slot/extensions--msdeploy/README.md b/avm/res/web/site/slot/extensions--msdeploy/README.md index cc50e99fbb..62bcdb5f31 100644 --- a/avm/res/web/site/slot/extensions--msdeploy/README.md +++ b/avm/res/web/site/slot/extensions--msdeploy/README.md @@ -12,7 +12,7 @@ This module deploys a Site extension for MSDeploy. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/extensions` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/sites/extensions) | +| `Microsoft.Web/sites/extensions` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/extensions) | ## Parameters @@ -21,6 +21,11 @@ This module deploys a Site extension for MSDeploy. | Parameter | Type | Description | | :-- | :-- | :-- | | [`appName`](#parameter-appname) | string | The name of the parent site resource. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | | [`msDeployConfiguration`](#parameter-msdeployconfiguration) | object | Sets the MSDeployment Properties. | ### Parameter: `appName` diff --git a/avm/res/web/site/slot/extensions--msdeploy/main.bicep b/avm/res/web/site/slot/extensions--msdeploy/main.bicep index 07d8ef3405..bf4220cf51 100644 --- a/avm/res/web/site/slot/extensions--msdeploy/main.bicep +++ b/avm/res/web/site/slot/extensions--msdeploy/main.bicep @@ -5,10 +5,10 @@ metadata owner = 'Azure/module-maintainers' @description('Required. The name of the parent site resource.') param appName string -@description('Required. Sets the MSDeployment Properties.') +@description('Optional. Sets the MSDeployment Properties.') param msDeployConfiguration object? -resource app 'Microsoft.Web/sites@2022-09-01' existing = { +resource app 'Microsoft.Web/sites@2023-12-01' existing = { name: appName } resource msdeploy 'Microsoft.Web/sites/extensions@2023-12-01' = { diff --git a/avm/res/web/site/slot/extensions--msdeploy/main.json b/avm/res/web/site/slot/extensions--msdeploy/main.json index 79be0b21b8..069239c100 100644 --- a/avm/res/web/site/slot/extensions--msdeploy/main.json +++ b/avm/res/web/site/slot/extensions--msdeploy/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "8769701913978391000" + "templateHash": "10249716032875912201" }, "name": "Site Deployment Extension ", "description": "This module deploys a Site extension for MSDeploy.", @@ -23,7 +23,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Required. Sets the MSDeployment Properties." + "description": "Optional. Sets the MSDeployment Properties." } } }, @@ -31,7 +31,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "msdeploy": { diff --git a/avm/res/web/site/slot/hybrid-connection-namespace/relay/README.md b/avm/res/web/site/slot/hybrid-connection-namespace/relay/README.md index 10dc977013..7e4e8b6a41 100644 --- a/avm/res/web/site/slot/hybrid-connection-namespace/relay/README.md +++ b/avm/res/web/site/slot/hybrid-connection-namespace/relay/README.md @@ -12,7 +12,7 @@ This module deploys a Site Slot Hybrid Connection Namespace Relay. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays` | [2022-09-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-09-01/sites/slots/hybridConnectionNamespaces/relays) | +| `Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays` | [2023-12-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2023-12-01/sites/slots/hybridConnectionNamespaces/relays) | ## Parameters diff --git a/avm/res/web/site/slot/hybrid-connection-namespace/relay/main.bicep b/avm/res/web/site/slot/hybrid-connection-namespace/relay/main.bicep index 6e85a49f08..21d7bd3fa0 100644 --- a/avm/res/web/site/slot/hybrid-connection-namespace/relay/main.bicep +++ b/avm/res/web/site/slot/hybrid-connection-namespace/relay/main.bicep @@ -27,7 +27,7 @@ resource namespace 'Microsoft.Relay/namespaces@2021-11-01' existing = { } } -resource hybridConnectionRelay 'Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays@2022-09-01' = { +resource hybridConnectionRelay 'Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays@2023-12-01' = { name: '${appName}/${slotName}/${namespace.name}/${namespace::hybridConnection.name}' properties: { serviceBusNamespace: namespace.name diff --git a/avm/res/web/site/slot/hybrid-connection-namespace/relay/main.json b/avm/res/web/site/slot/hybrid-connection-namespace/relay/main.json index 8fd1b8a2bb..accf1b996d 100644 --- a/avm/res/web/site/slot/hybrid-connection-namespace/relay/main.json +++ b/avm/res/web/site/slot/hybrid-connection-namespace/relay/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "1330320751784094185" + "templateHash": "12569198723769767672" }, "name": "Web/Function Apps Slot Hybrid Connection Relay", "description": "This module deploys a Site Slot Hybrid Connection Namespace Relay.", @@ -41,7 +41,7 @@ "resources": [ { "type": "Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}/{3}', parameters('appName'), parameters('slotName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]", "properties": { "serviceBusNamespace": "[split(parameters('hybridConnectionResourceId'), '/')[8]]", diff --git a/avm/res/web/site/slot/main.bicep b/avm/res/web/site/slot/main.bicep index 266ea3d893..2b560f783c 100644 --- a/avm/res/web/site/slot/main.bicep +++ b/avm/res/web/site/slot/main.bicep @@ -215,7 +215,7 @@ var formattedRoleAssignments = [ }) ] -resource app 'Microsoft.Web/sites@2021-03-01' existing = { +resource app 'Microsoft.Web/sites@2023-12-01' existing = { name: appName } @@ -534,7 +534,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/web/site/slot/main.json b/avm/res/web/site/slot/main.json index ede1b02e37..2607658182 100644 --- a/avm/res/web/site/slot/main.json +++ b/avm/res/web/site/slot/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "16398712095816733590" + "templateHash": "2418467213841620758" }, "name": "Web/Function App Deployment Slots", "description": "This module deploys a Web or Function App Deployment Slot.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -827,7 +827,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2021-03-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "slot": { @@ -987,7 +987,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "4751023237415156564" + "templateHash": "3011151783207983935" }, "name": "Site Slot App Settings", "description": "This module deploys a Site Slot App Setting.", @@ -1066,7 +1066,7 @@ "app::slot": { "existing": true, "type": "Microsoft.Web/sites/slots", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}', parameters('appName'), parameters('slotName'))]", "dependsOn": [ "app" @@ -1075,7 +1075,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "appInsight": { @@ -1091,7 +1091,7 @@ "condition": "[not(empty(parameters('storageAccountResourceId')))]", "existing": true, "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2023-01-01", + "apiVersion": "2023-05-01", "subscriptionId": "[split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2]]", "resourceGroup": "[split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]]", "name": "[last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))]" @@ -1101,7 +1101,7 @@ "apiVersion": "2022-09-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), 'appsettings')]", "kind": "[parameters('kind')]", - "properties": "[union(coalesce(parameters('currentAppSettings'), createObject()), coalesce(parameters('appSettingsKeyValuePairs'), createObject()), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/')), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), '2023-01-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), union(createObject('AzureWebJobsStorage__accountName', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), createObject('AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob)), createObject())), if(not(empty(parameters('appInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('appInsight').ConnectionString), createObject()))]", + "properties": "[union(coalesce(parameters('currentAppSettings'), createObject()), coalesce(parameters('appSettingsKeyValuePairs'), createObject()), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/')), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), '2023-05-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), union(createObject('AzureWebJobsStorage__accountName', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), createObject('AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob)), createObject())), if(not(empty(parameters('appInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('appInsight').ConnectionString), createObject()))]", "dependsOn": [ "appInsight", "app::slot", @@ -1170,7 +1170,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "12145671704242923554" + "templateHash": "7842363652527859767" }, "name": "Site Slot Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -1219,7 +1219,7 @@ "resources": [ { "type": "Microsoft.Web/sites/slots/config", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), 'authsettingsV2')]", "kind": "[parameters('kind')]", "properties": "[parameters('authSettingV2Configuration')]" @@ -1292,7 +1292,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "9837227282603977030" + "templateHash": "1564349757337430633" }, "name": "Web Site Slot Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Slot Basic Publishing Credentials Policy.", @@ -1339,7 +1339,7 @@ "resources": [ { "type": "Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), parameters('name'))]", "location": "[parameters('location')]", "properties": { @@ -1374,7 +1374,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies', parameters('appName'), parameters('slotName'), parameters('name')), '2022-09-01', 'full').location]" + "value": "[reference(resourceId('Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies', parameters('appName'), parameters('slotName'), parameters('name')), '2023-12-01', 'full').location]" } } } @@ -1418,7 +1418,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "1330320751784094185" + "templateHash": "12569198723769767672" }, "name": "Web/Function Apps Slot Hybrid Connection Relay", "description": "This module deploys a Site Slot Hybrid Connection Namespace Relay.", @@ -1454,7 +1454,7 @@ "resources": [ { "type": "Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[format('{0}/{1}/{2}/{3}', parameters('appName'), parameters('slotName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]", "properties": { "serviceBusNamespace": "[split(parameters('hybridConnectionResourceId'), '/')[8]]", @@ -1524,7 +1524,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "8769701913978391000" + "templateHash": "10249716032875912201" }, "name": "Site Deployment Extension ", "description": "This module deploys a Site extension for MSDeploy.", @@ -1541,7 +1541,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Required. Sets the MSDeployment Properties." + "description": "Optional. Sets the MSDeployment Properties." } } }, @@ -1549,7 +1549,7 @@ "app": { "existing": true, "type": "Microsoft.Web/sites", - "apiVersion": "2022-09-01", + "apiVersion": "2023-12-01", "name": "[parameters('appName')]" }, "msdeploy": { diff --git a/avm/res/web/site/version.json b/avm/res/web/site/version.json index bb03e3a03d..25beee1c2f 100644 --- a/avm/res/web/site/version.json +++ b/avm/res/web/site/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.10", + "version": "0.11", "pathFilters": [ "./main.json" ] diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index fda575fffb..a8e07b95db 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -20,7 +20,7 @@ This module deploys a Static Web App. | `Microsoft.Network/privateEndpoints` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints) | | `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints/privateDnsZoneGroups) | | `Microsoft.Web/staticSites` | [2021-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2021-03-01/staticSites) | -| `Microsoft.Web/staticSites/config` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/staticSites/config) | +| `Microsoft.Web/staticSites/config` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-03-01/staticSites/config) | | `Microsoft.Web/staticSites/customDomains` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-03-01/staticSites/customDomains) | | `Microsoft.Web/staticSites/linkedBackends` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-03-01/staticSites/linkedBackends) | @@ -874,15 +874,13 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | | [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | -### Parameter: `privateEndpoints.customDnsConfigs.fqdn` - -Fqdn that resolves to private endpoint IP address. +**Optional parameters** -- Required: No -- Type: string +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | FQDN that resolves to private endpoint IP address. | ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` @@ -891,6 +889,13 @@ A list of private IP addresses of the private endpoint. - Required: Yes - Type: array +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +FQDN that resolves to private endpoint IP address. + +- Required: No +- Type: string + ### Parameter: `privateEndpoints.customNetworkInterfaceName` The custom name of the network interface attached to the private endpoint. diff --git a/avm/res/web/static-site/config/README.md b/avm/res/web/static-site/config/README.md index d3c33bfabe..b129d6c357 100644 --- a/avm/res/web/static-site/config/README.md +++ b/avm/res/web/static-site/config/README.md @@ -12,7 +12,7 @@ This module deploys a Static Web App Site Config. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Web/staticSites/config` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/staticSites/config) | +| `Microsoft.Web/staticSites/config` | [2022-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2022-03-01/staticSites/config) | ## Parameters diff --git a/avm/res/web/static-site/main.bicep b/avm/res/web/static-site/main.bicep index c4c51912de..d481b9055e 100644 --- a/avm/res/web/static-site/main.bicep +++ b/avm/res/web/static-site/main.bicep @@ -408,7 +408,7 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint IP address.') + @description('Optional. FQDN that resolves to private endpoint IP address.') fqdn: string? @description('Required. A list of private IP addresses of the private endpoint.') diff --git a/avm/res/web/static-site/main.json b/avm/res/web/static-site/main.json index 490b5bd6df..8ca2581063 100644 --- a/avm/res/web/static-site/main.json +++ b/avm/res/web/static-site/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "9780314991768462863" + "version": "0.30.23.60470", + "templateHash": "6778188667859767695" }, "name": "Static Web Apps", "description": "This module deploys a Static Web App.", @@ -237,7 +237,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint IP address." + "description": "Optional. FQDN that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -647,8 +647,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "12808204824131403769" + "version": "0.30.23.60470", + "templateHash": "850520350862215676" }, "name": "Static Web App Site Linked Backends", "description": "This module deploys a Custom Function App into a Static Web App Site using the Linked Backends property.", @@ -749,8 +749,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6259766574135261184" + "version": "0.30.23.60470", + "templateHash": "1193937759400806376" }, "name": "Static Web App Site Config", "description": "This module deploys a Static Web App Site Config.", @@ -844,8 +844,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "6259766574135261184" + "version": "0.30.23.60470", + "templateHash": "1193937759400806376" }, "name": "Static Web App Site Config", "description": "This module deploys a Static Web App Site Config.", @@ -940,8 +940,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "4543869723891386084" + "version": "0.30.23.60470", + "templateHash": "777053581790816891" }, "name": "Static Web App Site Custom Domains", "description": "This module deploys a Static Web App Site Custom Domain.", diff --git a/avm/utilities/pipelines/e2eValidation/resourceRemoval/Initialize-DeploymentRemoval.ps1 b/avm/utilities/pipelines/e2eValidation/resourceRemoval/Initialize-DeploymentRemoval.ps1 index a4a98b8e2d..0b1f425880 100644 --- a/avm/utilities/pipelines/e2eValidation/resourceRemoval/Initialize-DeploymentRemoval.ps1 +++ b/avm/utilities/pipelines/e2eValidation/resourceRemoval/Initialize-DeploymentRemoval.ps1 @@ -73,6 +73,7 @@ function Initialize-DeploymentRemoval { $RemoveFirstSequence = @( 'Microsoft.Authorization/locks', 'Microsoft.VirtualMachineImages/imageTemplates', # Must be removed before their MSI & should be removed before its entities permissions are removed + 'Microsoft.DevOpsInfrastructure/pools' # Must be removed before vnet role assignments and other resources it depends on like a virtual network 'Microsoft.Authorization/roleAssignments', 'Microsoft.Insights/diagnosticSettings', 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups', @@ -94,7 +95,6 @@ function Initialize-DeploymentRemoval { 'Microsoft.ContainerInstance/containerGroups' # Must be removed before their MSI 'Microsoft.ManagedIdentity/userAssignedIdentities', 'Microsoft.Databricks/workspaces' - 'Microsoft.DevOpsInfrastructure/pools' # Must be removed before other resources it depends on like a virtual network 'Microsoft.Resources/resourceGroups' ) diff --git a/avm/utilities/pipelines/sharedScripts/Set-EnvironmentOnAgent.ps1 b/avm/utilities/pipelines/sharedScripts/Set-EnvironmentOnAgent.ps1 index bcfb7253ab..6823db5233 100644 --- a/avm/utilities/pipelines/sharedScripts/Set-EnvironmentOnAgent.ps1 +++ b/avm/utilities/pipelines/sharedScripts/Set-EnvironmentOnAgent.ps1 @@ -114,6 +114,9 @@ Optional. The PowerShell modules that should be installed on the agent. } ) +.PARAMETER InstallLatestPwshVersion +Optional. Enable to install the latest PowerShell version + .EXAMPLE Set-EnvironmentOnAgent @@ -133,7 +136,10 @@ function Set-EnvironmentOnAgent { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] - [Hashtable[]] $PSModules = @() + [Hashtable[]] $PSModules = @(), + + [Parameter(Mandatory = $false)] + [switch] $InstallLatestPwshVersion ) ############################ @@ -258,10 +264,12 @@ function Set-EnvironmentOnAgent { } Write-Verbose ('Install-CustomModule end') -Verbose +} - ##################################### - ## TEMP PowerShell installation ## - ##################################### +if ($InstallLatestPwshVersion) { + Write-Verbose '=======================' -Verbose + Write-Verbose 'PowerShell installation' -Verbose + Write-Verbose '=======================' -Verbose # Update the list of packages sudo apt-get update diff --git a/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 b/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 index ec32409602..00e5617b17 100644 --- a/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 +++ b/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 @@ -92,7 +92,7 @@ function Get-ReferenceObject { $moduleContent = $TemplateMap[$involvedFilePath] $resultSet.resourceReferences += @() + $moduleContent | Where-Object { $_ -match "^resource .+ '(.+?)' .+$" } | ForEach-Object { $matches[1] } - $resultSet.remoteReferences += @() + $moduleContent | Where-Object { $_ -match "^module .+ '(.+:.+?)' .+$" } | ForEach-Object { $matches[1] } + $resultSet.remoteReferences += @() + $moduleContent | Where-Object { $_ -match "^module .+ '(.+:.+?)' .+$" -or $_ -match "^import .+ '(.+:.+?)'$" } | ForEach-Object { $matches[1] } } return @{ diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 53a9508953..81d9d02186 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -629,7 +629,7 @@ Describe 'Module tests' -Tag 'Module' { if (-not $isRequired) { $description = $templateFileParameters.$parameter.metadata.description - if ($description -match "\('Required\.") { + if ($description -match '^Required\.') { $incorrectParameters += $parameter } } @@ -638,6 +638,27 @@ Describe 'Module tests' -Tag 'Module' { $incorrectParameters | Should -BeNullOrEmpty -Because ('only required parameters in the template file should have a description that starts with "Required.". Found incorrect items: [{0}].' -f ($incorrectParameters -join ', ')) } + It '[] All required parameters & UDTs in template file should have description that start with "(Required|Conditional).".' -TestCases $moduleFolderTestCases { + param ( + [hashtable] $templateFileContent, + [hashtable] $templateFileParameters + ) + + $incorrectParameters = @() + foreach ($parameter in ($templateFileParameters.PSBase.Keys | Sort-Object -Culture 'en-US')) { + $isRequired = Get-IsParameterRequired -TemplateFileContent $templateFileContent -Parameter $templateFileParameters.$parameter + + if ($isRequired) { + $description = $templateFileParameters.$parameter.metadata.description + if ($description -notmatch '^(Required|Conditional)\.') { + $incorrectParameters += $parameter + } + } + } + + $incorrectParameters | Should -BeNullOrEmpty -Because ('required parameters in the template file should have a description that starts with "Required.". Found incorrect items: [{0}].' -f ($incorrectParameters -join ', ')) + } + Context 'Schema-based User-defined-types tests' -Tag 'UDT' { # Creating custom test cases for the UDT schema-based tests @@ -667,34 +688,26 @@ Describe 'Module tests' -Tag 'Module' { $udtCases = @( @{ parameterName = 'diagnosticSettings' - udtName = 'diagnosticSettingType' link = "$interfaceBase/diagnostic-settings" } @{ - parameterName = 'roleAssignments' - udtName = 'roleAssignmentType' - udtExpectedUrl = "$interfaceBase/role-assignments/udt-schema" - link = "$interfaceBase/role-assignments" + parameterName = 'roleAssignments' + link = "$interfaceBase/role-assignments" } @{ - parameterName = 'lock' - udtName = 'lockType' - udtExpectedUrl = "$interfaceBase/resource-locks/udt-schema" - link = "$interfaceBase/resource-locks" + parameterName = 'lock' + link = "$interfaceBase/resource-locks" } @{ parameterName = 'managedIdentities' - udtName = 'managedIdentitiesType' link = "$interfaceBase/managed-identities" } @{ parameterName = 'privateEndpoints' - udtName = 'privateEndpointType' link = "$interfaceBase/private-endpoints" } @{ parameterName = 'customerManagedKey' - udtName = 'customerManagedKeyType' link = "$interfaceBase/customer-managed-keys" } ) @@ -705,86 +718,29 @@ Describe 'Module tests' -Tag 'Module' { templateFileContent = $templateFileContent templateFileContentBicep = Get-Content $templateFilePath parameterName = $udtCase.parameterName - udtName = $udtCase.udtName expectedUdtUrl = $udtCase.udtExpectedUrl ? $udtCase.udtExpectedUrl : '' link = $udtCase.link } } } - It '[] If template has a parameter [], it should implement the user-defined type []' -TestCases $udtTestCases { + It '[] If template has a parameter [], it should implement AVM''s corresponding user-defined type.' -TestCases $udtTestCases { param( [hashtable] $templateFileContent, [string[]] $templateFileContentBicep, [string] $parameterName, - [string] $udtName, - [string] $expectedUdtUrl, [string] $link ) if ($templateFileContent.parameters.Keys -contains $parameterName) { - $templateFileContent.parameters.$parameterName.Keys | Should -Contain '$ref' -Because "the [$parameterName] parameter should use a user-defined type. For information please review the [AVM Specs]($link)." - $templateFileContent.parameters.$parameterName.'$ref' | Should -Be "#/definitions/$udtName" -Because "the [$parameterName] parameter should use a user-defined type [$udtName]. For information please review the [AVM Specs]($link)." - - if (-not [String]::IsNullOrEmpty($expectedUdtUrl)) { - $implementedSchemaStartIndex = $templateFileContentBicep.IndexOf("type $udtName = {") - $implementedSchemaEndIndex = $implementedSchemaStartIndex + 1 - while ($templateFileContentBicep[$implementedSchemaEndIndex] -notmatch '^\}.*' -and $implementedSchemaEndIndex -lt $templateFileContentBicep.Length) { - $implementedSchemaEndIndex++ - } - if ($implementedSchemaEndIndex -eq $templateFileContentBicep.Length) { - throw "Failed to identify [$udtName] user-defined type in template." - } - $implementedSchema = $templateFileContentBicep[$implementedSchemaStartIndex..$implementedSchemaEndIndex] - - try { - $rawResponse = Invoke-WebRequest -Uri $expectedUdtUrl - if (($rawResponse.Headers['Content-Type'] | Out-String) -like '*text/plain*') { - $expectedSchemaFull = $rawResponse.Content -split '\n' - } else { - throw "Failed to fetch schema from [$expectedUdtUrl]. Skipping schema check" - } - } catch { - Write-Warning "Failed to fetch schema from [$expectedUdtUrl]. Skipping schema check" - return - } - - $expectedSchemaStartIndex = $expectedSchemaFull.IndexOf("type $udtName = {") - $expectedSchemaEndIndex = $expectedSchemaStartIndex + 1 - while ($expectedSchemaFull[$expectedSchemaEndIndex] -notmatch '^\}.*' -and $expectedSchemaEndIndex -lt $expectedSchemaFull.Length) { - $expectedSchemaEndIndex++ - } - if ($expectedSchemaEndIndex -eq $expectedSchemaFull.Length) { - throw "Failed to identify [$udtName] user-defined type in expected schema at URL [$expectedUdtUrl]." - } - $expectedSchema = $expectedSchemaFull[$expectedSchemaStartIndex..$expectedSchemaEndIndex] - - if ($templateFileContentBicep -match '@sys\.([a-zA-Z]+)\(') { - # Handing cases where the template may use the @sys namespace explicitly - $expectedSchema = $expectedSchema | ForEach-Object { $_ -replace '@([a-zA-Z]+)\(', '@sys.$1(' } - } - $formattedDiff = @() - foreach ($finding in (Compare-Object $implementedSchema $expectedSchema)) { - if ($finding.SideIndicator -eq '=>') { - $formattedDiff += ('+ {0}' -f $finding.InputObject) - } elseif ($finding.SideIndicator -eq '<=') { - $formattedDiff += ('- {0}' -f $finding.InputObject) - } - } - - if ($formattedDiff.Count -gt 0) { - $warningMessage = "The implemented user-defined type is not the same as the expected user-defined type ({0}) defined in the AVM specs ({1}) and should not have diff`n{2}" -f $expectedUdtUrl, $link, ($formattedDiff | Out-String) - Write-Warning $warningMessage - - # Adding also to output to show in GitHub CI - $mdFormattedDiff = ($formattedDiff -join '
    ') -replace '\|', '\|' - $mdFormattedWarningMessage = 'The implemented user-defined type is not the same as the expected [user-defined type]({0}) defined in the [AVM specs]({1}) and should not have diff
    {2}
    ' -f $expectedUdtUrl, $link, $mdFormattedDiff - Write-Output @{ - Warning = $mdFormattedWarningMessage - } - } + if ($templateFileContent.parameters.$parameterName.Keys -contains 'items') { + # If parameter is an array, the UDT may focus on each element + $templateFileContent.parameters.$parameterName.items.Keys | Should -Contain '$ref' -Because "the [$parameterName] parameter should use a user-defined type. For information please review the [AVM Specs]($link)." + } else { + # If not, the parameter itself should reference a UDT + $templateFileContent.parameters.$parameterName.Keys | Should -Contain '$ref' -Because "the [$parameterName] parameter should use a user-defined type. For information please review the [AVM Specs]($link)." } } else { Set-ItResult -Skipped -Because "the module template has no [$parameterName] parameter." diff --git a/avm/utilities/pipelines/staticValidation/psrule/.ps-rule/cb-waf-security.Rule.yaml b/avm/utilities/pipelines/staticValidation/psrule/.ps-rule/cb-waf-security.Rule.yaml new file mode 100644 index 0000000000..3620b3c9bd --- /dev/null +++ b/avm/utilities/pipelines/staticValidation/psrule/.ps-rule/cb-waf-security.Rule.yaml @@ -0,0 +1,46 @@ +--- +# Synopsis: Custom baseline for AVM WAF security pillar recommendations that are enforced in CI. +apiVersion: github.com/microsoft/PSRule/v1 +kind: Baseline +metadata: + name: CB.AVM.WAF.Security +spec: + rule: + include: + - Azure.ACR.AdminUser + - Azure.ACR.ContainerScan + - Azure.ACR.ContentTrust + - Azure.ACR.Firewall + - Azure.AKS.AzureRBAC + - Azure.AppGw.UseHTTPS + - Azure.AppGw.SSLPolicy + - Azure.AppGw.WAFEnabled + - Azure.AppGw.UseWAF + - Azure.AppService.WebSecureFtp + - Azure.AppService.MinTLS + - Azure.Cosmos.MinTLS + - Azure.Defender.Api + - Azure.Defender.AppServices + - Azure.Defender.Arm + - Azure.Defender.Containers + - Azure.Defender.CosmosDb + - Azure.Defender.Cspm + - Azure.Defender.Dns + - Azure.Defender.KeyVault + - Azure.Defender.OssRdb + - Azure.Defender.SQL + - Azure.Defender.SQLOnVM + - Azure.Defender.SecurityContact + - Azure.Defender.Servers + - Azure.Defender.Storage.DataScan + - Azure.Defender.Storage.MalwareScan + - Azure.Defender.Storage + - Azure.Firewall.Mode + - Azure.Firewall.PolicyMode + - Azure.Storage.DefenderCloud + - Azure.Storage.Defender.MalwareScan + - Azure.Storage.SecureTransfer + - Azure.Storage.BlobPublicAccess + - Azure.Storage.BlobAccessType + - Azure.Storage.Firewall + - Azure.Storage.MinTLS diff --git a/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml b/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml index 55cf9edc75..5ee3a07778 100644 --- a/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml +++ b/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml @@ -70,6 +70,7 @@ configuration: "ssoClientSecretKeyVaultPath", "ssoSecretType", "tokenValidityLength", + "uniqueKeyPolicyKeys", ] rule: diff --git a/avm/utl/types/avm-common-types/README.md b/avm/utl/types/avm-common-types/README.md new file mode 100644 index 0000000000..286bde8c8d --- /dev/null +++ b/avm/utl/types/avm-common-types/README.md @@ -0,0 +1,340 @@ +# Default interface types for AVM modules `[Types/AvmCommonTypes]` + +This module provides you with all common variants for AVM interfaces to be used in AVM modules. + +Details for how to implement these interfaces can be found in the AVM documentation [here](https://azure.github.io/Azure-Verified-Modules/specs/shared/interfaces). + + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) + +## Resource Types + +_None_ + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/utl/types/avm-common-types:`. + +- [Import all](#example-1-import-all) + +### Example 1: _Import all_ + +This example imports all available types of the given module. + +Note: In your module you would import only the types you need. + + + +
    + +via Bicep module + +```bicep +targetScope = 'subscription' + +metadata name = 'Import all' +metadata description = ''' +This example imports all available types of the given module. + +Note: In your module you would import only the types you need. +''' + +// ============== // +// Test Execution // +// ============== // + +import { + customerManagedKeyType + customerManagedKeyWithAutoRotateType + diagnosticSettingFullType + diagnosticSettingLogsOnlyType + diagnosticSettingMetricsOnlyType + roleAssignmentType + lockType + managedIdentityAllType + managedIdentityOnlySysAssignedType + managedIdentityOnlyUserAssignedType + privateEndpointMultiServiceType + privateEndpointSingleServiceType + secretToSetType + secretSetOutputType +} from '../../../main.bicep' // Would be: br/public:avm/utl/types/avm-common-types: + +// ====================== // +// Diagnostic Settings // +// ====================== // +param diagnosticFull diagnosticSettingFullType[] = [ + { + eventHubAuthorizationRuleResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.EventHub/namespaces/myNamespace/eventhubs/myHub/authorizationRules/myRule' + eventHubName: 'myHub' + logAnalyticsDestinationType: 'AzureDiagnostics' + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + { + category: 'jobs' + } + { + category: 'notebook' + } + ] + marketplacePartnerResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Datadog/monitors/dd1' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'mySettings' + storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Storage/storageAccounts/myStorageAccount' + workspaceResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myRg/providers/Microsoft.OperationalInsights/workspaces/myLaw' + } + { + eventHubAuthorizationRuleResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.EventHub/namespaces/myNamespace/eventhubs/myHub/authorizationRules/myRule' + eventHubName: 'myHub' + storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Storage/storageAccounts/myStorageAccount' + workspaceResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myRg/providers/Microsoft.OperationalInsights/workspaces/myLaw' + } +] +output diagnosticFullOutput diagnosticSettingFullType[] = diagnosticFull + +param diagnosticMetricsOnly diagnosticSettingMetricsOnlyType[] = [ + { + eventHubAuthorizationRuleResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.EventHub/namespaces/myNamespace/eventhubs/myHub/authorizationRules/myRule' + eventHubName: 'myHub' + logAnalyticsDestinationType: 'AzureDiagnostics' + marketplacePartnerResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Datadog/monitors/dd1' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'mySettings' + storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Storage/storageAccounts/myStorageAccount' + workspaceResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myRg/providers/Microsoft.OperationalInsights/workspaces/myLaw' + } +] +output diagnosticMetricsOnlyOutput diagnosticSettingFullType[] = diagnosticMetricsOnly + +param diagnosticLogsOnly diagnosticSettingLogsOnlyType[] = [ + { + eventHubAuthorizationRuleResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.EventHub/namespaces/myNamespace/eventhubs/myHub/authorizationRules/myRule' + eventHubName: 'myHub' + logAnalyticsDestinationType: 'AzureDiagnostics' + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + { + category: 'jobs' + } + { + category: 'notebook' + } + ] + marketplacePartnerResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Datadog/monitors/dd1' + name: 'mySettings' + storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Storage/storageAccounts/myStorageAccount' + workspaceResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myRg/providers/Microsoft.OperationalInsights/workspaces/myLaw' + } +] +output diagnosticLogsOnlyOutput diagnosticSettingFullType[] = diagnosticLogsOnly + +// =================== // +// Role Assignments // +// =================== // +param roleAssignments roleAssignmentType[] = [ + { + principalId: '11111111-1111-1111-1111-111111111111' + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) // Reader + condition: '((!(ActionMatches{\'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read\'})) OR (@Resource[Microsoft.Storage/storageAccounts/blobServices/containers:name] StringEquals \'blobs-example-container\'))' + conditionVersion: '2.0' + delegatedManagedIdentityResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' + description: 'my description' + name: 'myRoleAssignment' + principalType: 'ServicePrincipal' + } + { + principalId: '22222222-2222-2222-2222-222222222222' + roleDefinitionIdOrName: 'Reader' + principalType: 'ServicePrincipal' + } + { + principalId: '33333333-3333-3333-3333-333333333333' + roleDefinitionIdOrName: 'acdd72a7-3385-48ef-bd42-f606fba81ae7' //Reader + principalType: 'ServicePrincipal' + } +] +output roleAssignmentsOutput roleAssignmentType[] = roleAssignments + +// ========= // +// Locks // +// ========= // +param lock lockType = { + kind: 'CanNotDelete' + name: 'myLock' +} +output lockOutput lockType = lock + +// ====================== // +// Managed Idenitites // +// ====================== // +param managedIdentityFull managedIdentityAllType = { + systemAssigned: true + userAssignedResourceIds: [ + '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' + ] +} +output managedIdentityFullOutput managedIdentityAllType = managedIdentityFull + +param managedIdentityOnlySysAssigned managedIdentityOnlySysAssignedType = { + systemAssigned: true +} +output managedIdentityOnlySysAssignedOutput managedIdentityAllType = managedIdentityOnlySysAssigned + +param managedIdentityOnlyUserAssigned managedIdentityOnlyUserAssignedType = { + userAssignedResourceIds: [ + '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' + ] +} +output managedIdentityOnlyUserAssignedOutput managedIdentityAllType = managedIdentityOnlyUserAssigned + +// ===================== // +// Private Endpoints // +// ===================== // +param privateEndpointMultiService privateEndpointMultiServiceType[] = [ + { + lock: { + kind: 'CanNotDelete' + name: 'myLock' + } + roleAssignments: [ + { + principalId: '11111111-1111-1111-1111-111111111111' + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) // Reader + } + ] + subnetResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/defaultSubnet' + service: 'blob' + applicationSecurityGroupResourceIds: [ + '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/applicationSecurityGroups/myAsg' + ] + customDnsConfigs: [ + { + ipAddresses: [ + '1.2.3.4' + ] + } + ] + customNetworkInterfaceName: 'myInterface' + ipConfigurations: [ + { + name: 'myIpConfig' + properties: { + groupId: 'blob' + memberName: 'blob' + privateIPAddress: '1.2.3.4' + } + } + ] + isManualConnection: false + location: 'WestEurope' + manualConnectionRequestMessage: 'Please approve this connection.' + name: 'myPrivateEndpoint' + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/privateDnsZones/myZone' + name: 'myConfig' + } + ] + } + privateLinkServiceConnectionName: 'myConnection' + resourceGroupName: 'myResourceGroup' + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +] +output privateEndpointMultiServiceOutput privateEndpointMultiServiceType[] = privateEndpointMultiService + +param privateEndpointSingleService privateEndpointSingleServiceType[] = [ + { + subnetResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/defaultSubnet' + } +] +output privateEndpointSingleServiceOutput privateEndpointSingleServiceType[] = privateEndpointSingleService + +// ======================== // +// Customer-Managed Keys // +// ======================== // +param customerManagedKeyFull customerManagedKeyType = { + keyName: 'myKey' + keyVaultResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.KeyVault/vaults/myVault' + keyVersion: '2f4783701d724537a4e0c2d473c31846' + userAssignedIdentityResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' +} +output customerManagedKeyFullOutput customerManagedKeyType = customerManagedKeyFull + +param customerManagedKeyDefaults customerManagedKeyType = { + keyName: 'myKey' + keyVaultResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.KeyVault/vaults/myVault' +} +output customerManagedKeyDefaultsOutput customerManagedKeyType = customerManagedKeyDefaults + +param customerManagedKeyWithAutoRotate customerManagedKeyWithAutoRotateType = { + keyName: 'myKey' + keyVaultResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.KeyVault/vaults/myVault' + autoRotationDisabled: true + userAssignedIdentityResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' +} +output customerManagedKeyWithAutoRotateOutput customerManagedKeyWithAutoRotateType = customerManagedKeyWithAutoRotate + +// ================== // +// Secrets Export // +// ================== // +param secretToSet secretToSetType[] = [ + { + name: 'mySecret' + value: 'definitelyAValue' + } +] +#disable-next-line outputs-should-not-contain-secrets // Does not contain a secret +output secretToSetOutput secretToSetType[] = secretToSet + +param secretSet secretSetOutputType[] = [ + { + secretResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.KeyVault/vaults/myVault/secrets/mySecret' + secretUri: 'https://myVault.${az.environment().suffixes.keyvaultDns}/secrets/mySecret' + secretUriWithVersion: 'https://myVault.${az.environment().suffixes.keyvaultDns}/secrets/mySecret/2f4783701d724537a4e0c2d473c31846' + } +] +output secretSetOutput secretSetOutputType[] = secretSet +``` + +
    +

    + +## Parameters + +_None_ + +## Outputs + +_None_ diff --git a/avm/utl/types/avm-common-types/main.bicep b/avm/utl/types/avm-common-types/main.bicep new file mode 100644 index 0000000000..0fb1f0bbc8 --- /dev/null +++ b/avm/utl/types/avm-common-types/main.bicep @@ -0,0 +1,431 @@ +metadata name = 'Default interface types for AVM modules' +metadata description = ''' +This module provides you with all common variants for AVM interfaces to be used in AVM modules. + +Details for how to implement these interfaces can be found in the AVM documentation [here](https://azure.github.io/Azure-Verified-Modules/specs/shared/interfaces). +''' +metadata owner = 'Azure/module-maintainers' + +// ====================== // +// Diagnostic Settings // +// ====================== // + +// Type with all properties available +@export() +@description('An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.') +type diagnosticSettingFullType = { + @description('Optional. The name of the diagnostic setting.') + name: string? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') + logCategoriesAndGroups: { + @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') + category: string? + + @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') + categoryGroup: string? + + @description('Optional. Enable or disable the category explicitly. Default is `true`.') + enabled: bool? + }[]? + + @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') + category: string + + @description('Optional. Enable or disable the category explicitly. Default is `true`.') + enabled: bool? + }[]? + + @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') + logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? + + @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.') + workspaceResourceId: string? + + @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.') + storageAccountResourceId: 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.') + eventHubAuthorizationRuleResourceId: 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.') + eventHubName: string? + + @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +} + +@export() +@description('An AVM-aligned type for a diagnostic setting. To be used if only metrics are supported by the resource provider.') +type diagnosticSettingMetricsOnlyType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to `[]` to disable metric collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') + category: string + + @description('Optional. Enable or disable the category explicitly. Default is `true`.') + enabled: bool? + }[]? + + @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') + logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? + + @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.') + workspaceResourceId: string? + + @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.') + storageAccountResourceId: 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.') + eventHubAuthorizationRuleResourceId: 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.') + eventHubName: string? + + @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +} + +@export() +@description('An AVM-aligned type for a diagnostic setting. To be used if only logs are supported by the resource provider.') +type diagnosticSettingLogsOnlyType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to `[]` to disable log collection.') + logCategoriesAndGroups: { + @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') + category: string? + + @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs.') + categoryGroup: string? + + @description('Optional. Enable or disable the category explicitly. Default is `true`.') + enabled: bool? + }[]? + + @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') + logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? + + @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.') + workspaceResourceId: string? + + @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.') + storageAccountResourceId: 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.') + eventHubAuthorizationRuleResourceId: 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.') + eventHubName: string? + + @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +} + +// =================== // +// Role Assignments // +// =================== // + +@export() +@description('An AVM-aligned type for a role assignment.') +type roleAssignmentType = { + @description('Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated.') + name: string? + + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +} + +// ========= // +// Locks // +// ========= // + +@export() +@description('An AVM-aligned type for a lock.') +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +} + +// ====================== // +// Managed Identities // +// ====================== // + +@export() +@description('An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.') +type managedIdentityAllType = { + @description('Optional. Enables system assigned managed identity on the resource.') + systemAssigned: bool? + + @description('Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption.') + userAssignedResourceIds: string[]? +} + +@export() +@description('An AVM-aligned type for a managed identity configuration. To be used if only system-assigned identities are supported by the resource provider.') +type managedIdentityOnlySysAssignedType = { + @description('Optional. Enables system assigned managed identity on the resource.') + systemAssigned: bool? +} + +@export() +@description('An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.') +type managedIdentityOnlyUserAssignedType = { + @description('Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption.') + userAssignedResourceIds: string[]? +} + +// ===================== // +// Private Endpoints // +// ===================== // + +type privateEndpointPrivateDnsZoneGroupType = { + @description('Optional. The name of the Private DNS Zone Group.') + name: string? + + @description('Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones.') + privateDnsZoneGroupConfigs: { + @description('Optional. The name of the private DNS Zone Group config.') + name: string? + + @description('Required. The resource id of the private DNS zone.') + privateDnsZoneResourceId: string + }[] +} + +type privateEndpointCustomDnsConfigType = { + @description('Optional. FQDN that resolves to private endpoint IP address.') + fqdn: string? + + @description('Required. A list of private IP addresses of the private endpoint.') + ipAddresses: string[] +} + +type privateEndpointIpConfigurationType = { + @description('Required. The name of the resource that is unique within a resource group.') + name: string + + @description('Required. Properties of private endpoint IP configurations.') + properties: { + @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') + groupId: string + + @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') + memberName: string + + @description('Required. A private IP address obtained from the private endpoint\'s subnet.') + privateIPAddress: string + } +} + +@export() +@description('An AVM-aligned type for a private endpoint. To be used if the private endpoint\'s default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like \'vault\' for key vault).') +type privateEndpointSingleServiceType = { + @description('Optional. The name of the Private Endpoint.') + name: string? + + @description('Optional. The location to deploy the Private Endpoint to.') + location: string? + + @description('Optional. The name of the private link connection to create.') + privateLinkServiceConnectionName: string? + + @description('Optional. The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint.') + service: string? + + @description('Required. Resource ID of the subnet where the endpoint needs to be created.') + subnetResourceId: string + + @description('Optional. The private DNS Zone Group to configure for the Private Endpoint.') + privateDnsZoneGroup: privateEndpointPrivateDnsZoneGroupType? + + @description('Optional. If Manual Private Link Connection is required.') + isManualConnection: bool? + + @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') + @maxLength(140) + manualConnectionRequestMessage: string? + + @description('Optional. Custom DNS configurations.') + customDnsConfigs: privateEndpointCustomDnsConfigType[]? + + @description('Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints.') + ipConfigurations: privateEndpointIpConfigurationType[]? + + @description('Optional. Application security groups in which the Private Endpoint IP configuration is included.') + applicationSecurityGroupResourceIds: string[]? + + @description('Optional. The custom name of the network interface attached to the Private Endpoint.') + customNetworkInterfaceName: string? + + @description('Optional. Specify the type of lock.') + lock: lockType? + + @description('Optional. Array of role assignments to create.') + roleAssignments: roleAssignmentType[]? + + @description('Optional. Tags to be applied on all resources/Resource Groups in this deployment.') + tags: object? + + @description('Optional. Enable/Disable usage telemetry for module.') + enableTelemetry: bool? + + @description('Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource.') + resourceGroupName: string? +} + +@export() +@description('An AVM-aligned type for a private endpoint. To be used if the private endpoint\'s default service / groupId can NOT be assumed (i.e., for services that have more than one subresource, like Storage Account with Blob (blob, table, queue, file, ...).') +type privateEndpointMultiServiceType = { + @description('Optional. The name of the private endpoint.') + name: string? + + @description('Optional. The location to deploy the private endpoint to.') + location: string? + + @description('Optional. The name of the private link connection to create.') + privateLinkServiceConnectionName: string? + + @description('Required. The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file" for a Storage Account\'s Private Endpoints.') + service: string + + @description('Required. Resource ID of the subnet where the endpoint needs to be created.') + subnetResourceId: string + + @description('Optional. The private DNS zone group to configure for the private endpoint.') + privateDnsZoneGroup: privateEndpointPrivateDnsZoneGroupType? + + @description('Optional. If Manual Private Link Connection is required.') + isManualConnection: bool? + + @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') + @maxLength(140) + manualConnectionRequestMessage: string? + + @description('Optional. Custom DNS configurations.') + customDnsConfigs: privateEndpointCustomDnsConfigType[]? + + @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') + ipConfigurations: privateEndpointIpConfigurationType[]? + + @description('Optional. Application security groups in which the private endpoint IP configuration is included.') + applicationSecurityGroupResourceIds: string[]? + + @description('Optional. The custom name of the network interface attached to the private endpoint.') + customNetworkInterfaceName: string? + + @description('Optional. Specify the type of lock.') + lock: lockType? + + @description('Optional. Array of role assignments to create.') + roleAssignments: roleAssignmentType[]? + + @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') + tags: object? + + @description('Optional. Enable/Disable usage telemetry for module.') + enableTelemetry: bool? + + @description('Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource.') + resourceGroupName: string? +} + +// ======================== // +// Customer-Managed Keys // +// ======================== // + +@export() +@description('An AVM-aligned type for a customer-managed key. To be used if the resource type does not support auto-rotation of the customer-managed key.') +type customerManagedKeyType = { + @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') + keyVaultResourceId: string + + @description('Required. The name of the customer managed key to use for encryption.') + keyName: string + + @description('Optional. The version of the customer managed key to reference for encryption. If not provided, the deployment will use the latest version available at deployment time.') + keyVersion: string? + + @description('Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use.') + userAssignedIdentityResourceId: string? +} + +@export() +@description('An AVM-aligned type for a customer-managed key. To be used if the resource type supports auto-rotation of the customer-managed key.') +type customerManagedKeyWithAutoRotateType = { + @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') + keyVaultResourceId: string + + @description('Required. The name of the customer managed key to use for encryption.') + keyName: string + + @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using version as per \'autoRotationDisabled\' setting.') + keyVersion: string? + + @description('Optional. If configured, instead of auto-rotating to the latest key version, the latest key version at the time of the deployment is used.') + autoRotationDisabled: bool? + + @description('Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use.') + userAssignedIdentityResourceId: string? +} + +// ================== // +// Secrets Export // +// ================== // +@export() +@description('An AVM-aligned type for the secret to set via the secrets export feature.') +type secretToSetType = { + @description('Required. The name of the secret to set.') + name: string + + @description('Required. The value of the secret to set.') + @secure() + value: string +} + +@export() +@description('An AVM-aligned type for the output of the secret set via the secrets export feature.') +type secretSetOutputType = { + @description('The resourceId of the exported secret.') + secretResourceId: string + + @description('The secret URI of the exported secret.') + secretUri: string + + @description('The secret URI with version of the exported secret.') + secretUriWithVersion: string +} + +@export() +@description('A map of the exported secrets') +type secretsOutputType = { + @description('An exported secret\'s references.') + *: secretSetOutputType +} diff --git a/avm/utl/types/avm-common-types/main.json b/avm/utl/types/avm-common-types/main.json new file mode 100644 index 0000000000..f13c5001d0 --- /dev/null +++ b/avm/utl/types/avm-common-types/main.json @@ -0,0 +1,994 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "18359033509174375913" + }, + "name": "Default interface types for AVM modules", + "description": "This module provides you with all common variants for AVM interfaces to be used in AVM modules.\n\nDetails for how to implement these interfaces can be found in the AVM documentation [here](https://azure.github.io/Azure-Verified-Modules/specs/shared/interfaces).\n", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider." + } + }, + "diagnosticSettingMetricsOnlyType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a diagnostic setting. To be used if only metrics are supported by the resource provider." + } + }, + "diagnosticSettingLogsOnlyType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "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." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a diagnostic setting. To be used if only logs are supported by the resource provider." + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, 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 ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a role assignment." + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a lock." + } + }, + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider." + } + }, + "managedIdentityOnlySysAssignedType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a managed identity configuration. To be used if only system-assigned identities are supported by the resource provider." + } + }, + "managedIdentityOnlyUserAssignedType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider." + } + }, + "privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS Zone Group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." + } + } + } + }, + "privateEndpointCustomDnsConfigType": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "privateEndpointSingleServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private Endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the Private Endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the Private Endpoint for. For example \"vault\" for a Key Vault Private Endpoint." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS Zone Group to configure for the Private Endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointCustomDnsConfigType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointIpConfigurationType" + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the Private Endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the Private Endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/Resource Groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different Resource Group than the main resource." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like 'vault' for key vault)." + } + }, + "privateEndpointMultiServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "metadata": { + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\" for a Storage Account's Private Endpoints." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointCustomDnsConfigType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointIpConfigurationType" + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can NOT be assumed (i.e., for services that have more than one subresource, like Storage Account with Blob (blob, table, queue, file, ...)." + } + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, the deployment will use the latest version available at deployment time." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a customer-managed key. To be used if the resource type does not support auto-rotation of the customer-managed key." + } + }, + "customerManagedKeyWithAutoRotateType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using version as per 'autoRotationDisabled' setting." + } + }, + "autoRotationDisabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If configured, instead of auto-rotating to the latest key version, the latest key version at the time of the deployment is used." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for a customer-managed key. To be used if the resource type supports auto-rotation of the customer-managed key." + } + }, + "secretToSetType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret to set." + } + }, + "value": { + "type": "securestring", + "metadata": { + "description": "Required. The value of the secret to set." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for the secret to set via the secrets export feature." + } + }, + "secretSetOutputType": { + "type": "object", + "properties": { + "secretResourceId": { + "type": "string", + "metadata": { + "description": "The resourceId of the exported secret." + } + }, + "secretUri": { + "type": "string", + "metadata": { + "description": "The secret URI of the exported secret." + } + }, + "secretUriWithVersion": { + "type": "string", + "metadata": { + "description": "The secret URI with version of the exported secret." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "An AVM-aligned type for the output of the secret set via the secrets export feature." + } + }, + "secretsOutputType": { + "type": "object", + "properties": {}, + "additionalProperties": { + "$ref": "#/definitions/secretSetOutputType", + "metadata": { + "description": "An exported secret's references." + } + }, + "metadata": { + "__bicep_export!": true, + "description": "A map of the exported secrets" + } + } + }, + "resources": {} +} \ No newline at end of file diff --git a/avm/utl/types/avm-common-types/tests/e2e/import/main.test.bicep b/avm/utl/types/avm-common-types/tests/e2e/import/main.test.bicep new file mode 100644 index 0000000000..f6a755034d --- /dev/null +++ b/avm/utl/types/avm-common-types/tests/e2e/import/main.test.bicep @@ -0,0 +1,287 @@ +targetScope = 'subscription' + +metadata name = 'Import all' +metadata description = ''' +This example imports all available types of the given module. + +Note: In your module you would import only the types you need. +''' + +// ============== // +// Test Execution // +// ============== // + +import { + customerManagedKeyType + customerManagedKeyWithAutoRotateType + diagnosticSettingFullType + diagnosticSettingLogsOnlyType + diagnosticSettingMetricsOnlyType + roleAssignmentType + lockType + managedIdentityAllType + managedIdentityOnlySysAssignedType + managedIdentityOnlyUserAssignedType + privateEndpointMultiServiceType + privateEndpointSingleServiceType + secretToSetType + secretSetOutputType +} from '../../../main.bicep' // Would be: br/public:avm/utl/types/avm-common-types: + +// ====================== // +// Diagnostic Settings // +// ====================== // +param diagnosticFull diagnosticSettingFullType[] = [ + { + eventHubAuthorizationRuleResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.EventHub/namespaces/myNamespace/eventhubs/myHub/authorizationRules/myRule' + eventHubName: 'myHub' + logAnalyticsDestinationType: 'AzureDiagnostics' + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + { + category: 'jobs' + } + { + category: 'notebook' + } + ] + marketplacePartnerResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Datadog/monitors/dd1' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'mySettings' + storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Storage/storageAccounts/myStorageAccount' + workspaceResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myRg/providers/Microsoft.OperationalInsights/workspaces/myLaw' + } + { + eventHubAuthorizationRuleResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.EventHub/namespaces/myNamespace/eventhubs/myHub/authorizationRules/myRule' + eventHubName: 'myHub' + storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Storage/storageAccounts/myStorageAccount' + workspaceResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myRg/providers/Microsoft.OperationalInsights/workspaces/myLaw' + } +] +output diagnosticFullOutput diagnosticSettingFullType[] = diagnosticFull + +param diagnosticMetricsOnly diagnosticSettingMetricsOnlyType[] = [ + { + eventHubAuthorizationRuleResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.EventHub/namespaces/myNamespace/eventhubs/myHub/authorizationRules/myRule' + eventHubName: 'myHub' + logAnalyticsDestinationType: 'AzureDiagnostics' + marketplacePartnerResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Datadog/monitors/dd1' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'mySettings' + storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Storage/storageAccounts/myStorageAccount' + workspaceResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myRg/providers/Microsoft.OperationalInsights/workspaces/myLaw' + } +] +output diagnosticMetricsOnlyOutput diagnosticSettingFullType[] = diagnosticMetricsOnly + +param diagnosticLogsOnly diagnosticSettingLogsOnlyType[] = [ + { + eventHubAuthorizationRuleResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.EventHub/namespaces/myNamespace/eventhubs/myHub/authorizationRules/myRule' + eventHubName: 'myHub' + logAnalyticsDestinationType: 'AzureDiagnostics' + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + { + category: 'jobs' + } + { + category: 'notebook' + } + ] + marketplacePartnerResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Datadog/monitors/dd1' + name: 'mySettings' + storageAccountResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Storage/storageAccounts/myStorageAccount' + workspaceResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myRg/providers/Microsoft.OperationalInsights/workspaces/myLaw' + } +] +output diagnosticLogsOnlyOutput diagnosticSettingFullType[] = diagnosticLogsOnly + +// =================== // +// Role Assignments // +// =================== // +param roleAssignments roleAssignmentType[] = [ + { + principalId: '11111111-1111-1111-1111-111111111111' + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) // Reader + condition: '((!(ActionMatches{\'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read\'})) OR (@Resource[Microsoft.Storage/storageAccounts/blobServices/containers:name] StringEquals \'blobs-example-container\'))' + conditionVersion: '2.0' + delegatedManagedIdentityResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' + description: 'my description' + name: 'myRoleAssignment' + principalType: 'ServicePrincipal' + } + { + principalId: '22222222-2222-2222-2222-222222222222' + roleDefinitionIdOrName: 'Reader' + principalType: 'ServicePrincipal' + } + { + principalId: '33333333-3333-3333-3333-333333333333' + roleDefinitionIdOrName: 'acdd72a7-3385-48ef-bd42-f606fba81ae7' //Reader + principalType: 'ServicePrincipal' + } +] +output roleAssignmentsOutput roleAssignmentType[] = roleAssignments + +// ========= // +// Locks // +// ========= // +param lock lockType = { + kind: 'CanNotDelete' + name: 'myLock' +} +output lockOutput lockType = lock + +// ====================== // +// Managed Idenitites // +// ====================== // +param managedIdentityFull managedIdentityAllType = { + systemAssigned: true + userAssignedResourceIds: [ + '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' + ] +} +output managedIdentityFullOutput managedIdentityAllType = managedIdentityFull + +param managedIdentityOnlySysAssigned managedIdentityOnlySysAssignedType = { + systemAssigned: true +} +output managedIdentityOnlySysAssignedOutput managedIdentityAllType = managedIdentityOnlySysAssigned + +param managedIdentityOnlyUserAssigned managedIdentityOnlyUserAssignedType = { + userAssignedResourceIds: [ + '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' + ] +} +output managedIdentityOnlyUserAssignedOutput managedIdentityAllType = managedIdentityOnlyUserAssigned + +// ===================== // +// Private Endpoints // +// ===================== // +param privateEndpointMultiService privateEndpointMultiServiceType[] = [ + { + lock: { + kind: 'CanNotDelete' + name: 'myLock' + } + roleAssignments: [ + { + principalId: '11111111-1111-1111-1111-111111111111' + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) // Reader + } + ] + subnetResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/defaultSubnet' + service: 'blob' + applicationSecurityGroupResourceIds: [ + '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/applicationSecurityGroups/myAsg' + ] + customDnsConfigs: [ + { + ipAddresses: [ + '1.2.3.4' + ] + } + ] + customNetworkInterfaceName: 'myInterface' + ipConfigurations: [ + { + name: 'myIpConfig' + properties: { + groupId: 'blob' + memberName: 'blob' + privateIPAddress: '1.2.3.4' + } + } + ] + isManualConnection: false + location: 'WestEurope' + manualConnectionRequestMessage: 'Please approve this connection.' + name: 'myPrivateEndpoint' + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/privateDnsZones/myZone' + name: 'myConfig' + } + ] + } + privateLinkServiceConnectionName: 'myConnection' + resourceGroupName: 'myResourceGroup' + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +] +output privateEndpointMultiServiceOutput privateEndpointMultiServiceType[] = privateEndpointMultiService + +param privateEndpointSingleService privateEndpointSingleServiceType[] = [ + { + subnetResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/defaultSubnet' + } +] +output privateEndpointSingleServiceOutput privateEndpointSingleServiceType[] = privateEndpointSingleService + +// ======================== // +// Customer-Managed Keys // +// ======================== // +param customerManagedKeyFull customerManagedKeyType = { + keyName: 'myKey' + keyVaultResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.KeyVault/vaults/myVault' + keyVersion: '2f4783701d724537a4e0c2d473c31846' + userAssignedIdentityResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' +} +output customerManagedKeyFullOutput customerManagedKeyType = customerManagedKeyFull + +param customerManagedKeyDefaults customerManagedKeyType = { + keyName: 'myKey' + keyVaultResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.KeyVault/vaults/myVault' +} +output customerManagedKeyDefaultsOutput customerManagedKeyType = customerManagedKeyDefaults + +param customerManagedKeyWithAutoRotate customerManagedKeyWithAutoRotateType = { + keyName: 'myKey' + keyVaultResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.KeyVault/vaults/myVault' + autoRotationDisabled: true + userAssignedIdentityResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity' +} +output customerManagedKeyWithAutoRotateOutput customerManagedKeyWithAutoRotateType = customerManagedKeyWithAutoRotate + +// ================== // +// Secrets Export // +// ================== // +param secretToSet secretToSetType[] = [ + { + name: 'mySecret' + value: 'definitelyAValue' + } +] +#disable-next-line outputs-should-not-contain-secrets // Does not contain a secret +output secretToSetOutput secretToSetType[] = secretToSet + +param secretSet secretSetOutputType[] = [ + { + secretResourceId: '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.KeyVault/vaults/myVault/secrets/mySecret' + secretUri: 'https://myVault.${az.environment().suffixes.keyvaultDns}/secrets/mySecret' + secretUriWithVersion: 'https://myVault.${az.environment().suffixes.keyvaultDns}/secrets/mySecret/2f4783701d724537a4e0c2d473c31846' + } +] +output secretSetOutput secretSetOutputType[] = secretSet diff --git a/avm/utl/types/avm-common-types/version.json b/avm/utl/types/avm-common-types/version.json new file mode 100644 index 0000000000..c177b1bb58 --- /dev/null +++ b/avm/utl/types/avm-common-types/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.3", + "pathFilters": [ + "./main.json" + ] +} \ No newline at end of file